Q1

This question will focus entirely on NumPy arrays: vectorized programming, slicing, and broadcasting.

Part A

In this question, you'll implement the vector dot product.

Write a function which:

  • is named dot
  • takes two NumPy arrays as arguments
  • returns one number: the floating-point dot product of the two input vectors

Recall how a dot product works: corresponding elements of two arrays are multiplied together, then all these products are summed.

For example: if I have two NumPy arrays [1, 2, 3] and [4, 5, 6], their dot product would be (1*4) + (2*5) + (3*6), or 4 + 10 + 18, or 32.

You can use NumPy arrays, and the np.sum() function, but no other NumPy functions.


In [ ]:


In [ ]:
import numpy as np
np.random.seed(57442)

x1 = np.random.random(10)
x2 = np.random.random(10)
np.testing.assert_allclose(x1.dot(x2), dot(x1, x2))

In [ ]:
np.random.seed(495835)

x1 = np.random.random(100)
x2 = np.random.random(100)
np.testing.assert_allclose(x1.dot(x2), dot(x1, x2))

Part B

Write a function which:

  • is named subarray
  • takes two arguments, both NumPy arrays: one containing data, one containing indices
  • returns one NumPy array

The function should return a NumPy array that corresponds to the elements of the input array of data selected by the indices array.

For example, subarray([1, 2, 3], [2]) should return a NumPy array of [3].

You cannot use any built-in functions, NumPy functions, or loops!


In [ ]:


In [ ]:
import numpy as np
np.random.seed(5381)

x1 = np.random.random(43)
i1 = np.random.randint(0, 43, 10)
a1 = np.array([ 0.24317871,  0.16900041,  0.20687451,  0.38726974,  0.49798077,
        0.32797843,  0.18801287,  0.29021025,  0.65418547,  0.78651195])
np.testing.assert_allclose(a1, subarray(x1, i1), rtol = 1e-5)

In [ ]:
x2 = np.random.random(74)
i2 = np.random.randint(0, 74, 5)
a2 = np.array([ 0.96372034,  0.84256813,  0.08188566,  0.71852542,  0.92384611])
np.testing.assert_allclose(a2, subarray(x2, i2), rtol = 1e-5)

Part C

Write a function which:

  • is named less_than
  • takes two arguments: a NumPy array, and a floating-point number
  • returns a NumPy array

You should use a boolean mask to return only the values in the NumPy array that are less than the specified floating-point value (the second parameter). No loops are allowed, or any built-in functions or loops.

For example, less_than([1, 2, 3], 2.5) should return a NumPy array of [1, 2].


In [ ]:


In [ ]:
import numpy as np
np.random.seed(85928)

x = np.random.random((10, 20, 30))
t = 0.001
y = np.array([ 0.0005339 ,  0.00085714,  0.00091265,  0.00037283])
np.testing.assert_allclose(y, less_than(x, t))

In [ ]:
np.random.seed(8643)

x2 = np.random.random((100, 100, 10))
t2 = 0.0001
y2 = np.array([  2.91560413e-06,   6.80065620e-06,   3.63294064e-05,
         7.50659065e-05,   1.61602031e-06,   9.37205052e-05])
np.testing.assert_allclose(y2, less_than(x2, t2), rtol = 1e-05)

Part D

Write a function which:

  • is named greater_than
  • takes two arguments: a NumPy array, and a threshold number (float)
  • returns a NumPy array

You should use a boolean mask to return only the values in the NumPy array that are greater than the specified threshold value (the second parameter). No loops are allowed, or built-in functions, or NumPy functions.

For example, greater_than([1, 2, 3], 2.5) should return a NumPy array of [3].


In [ ]:


In [ ]:
import numpy as np
np.random.seed(592582)

x = np.random.random((10, 20, 30))
t = 0.999
y = np.array([ 0.99910167,  0.99982779,  0.99982253,  0.9991043 ])
np.testing.assert_allclose(y, greater_than(x, t))

In [ ]:
np.random.seed(689388)

x2 = np.random.random((100, 100, 10))
t2 = 0.9999
y2 = np.array([ 0.99997265,  0.99991169,  0.99998906,  0.99999012,  0.99992325,
        0.99993289,  0.99996637,  0.99996416,  0.99992627,  0.99994388,
        0.99993102,  0.99997486,  0.99992968,  0.99997598])
np.testing.assert_allclose(y2, greater_than(x2, t2), rtol = 1e-05)

Part E

Write a function which:

  • is named in_between
  • takes three parameters: a NumPy array, a lower threshold (float), and an upper threshold (float)
  • returns a NumPy array

You should use a boolean mask to return only the values in the NumPy array that are in between the two specified threshold values, lower and upper. No loops are allowed, or built-in functions, or NumPy functions.

For example, in_between([1, 2, 3], 1, 3) should return a NumPy array of [2].

Hint: you can use your functions from Parts C and D to help!


In [ ]:


In [ ]:
import numpy as np
np.random.seed(7472)

x = np.random.random((10, 20, 30))
lo = 0.499
hi = 0.501
y = np.array([ 0.50019884,  0.50039172,  0.500711  ,  0.49983418,  0.49942259,
        0.4994417 ,  0.49979261,  0.50029046,  0.5008376 ,  0.49985266,
        0.50015914,  0.50068227,  0.50060399,  0.49968918,  0.50091042,
        0.50063015,  0.50050032])
np.testing.assert_allclose(y, in_between(x, lo, hi))

In [ ]:
import numpy as np
np.random.seed(14985)

x = np.random.random((30, 40, 50))
lo = 0.49999
hi = 0.50001
y = np.array([ 0.50000714,  0.49999045])
np.testing.assert_allclose(y, in_between(x, lo, hi))

Part F

Write a function which:

  • is named not_in_between
  • takes three parameters: a NumPy array, a lower threshold (float), and an upper threshold (float)
  • returns a NumPy array

You should use a boolean mask to return only the values in the NumPy array that are NOT in between the two specified threshold values, lower and upper. No loops are allowed, or built-in functions, or NumPy functions.

For example, not_in_between([1, 2, 3, 4], 1, 3) should return a NumPy array of [4].

Hint: you can use your functions from Parts C and D to help!


In [ ]:


In [ ]:
import numpy as np
np.random.seed(475185)

x = np.random.random((10, 20, 30))
lo = 0.001
hi = 0.999
y = np.array([  9.52511605e-04,   8.62993716e-04,   3.70243252e-04,
         9.99945849e-01,   7.21751759e-04,   9.36931041e-04,
         5.10792605e-04,   6.44911672e-04])
np.testing.assert_allclose(y, not_in_between(x, lo, hi))

In [ ]:
np.random.seed(51954)

x = np.random.random((30, 40, 50))
lo = 0.00001
hi = 0.99999
y = np.array([  8.46159001e-06,   9.99998669e-01,   9.99993873e-01,
         5.58488698e-06,   9.99993348e-01])
np.testing.assert_allclose(y, not_in_between(x, lo, hi))

Part G

Write a function which:

  • is named reverse_array
  • takes 1 parameter: a 1D NumPy array of data
  • returns the 1D NumPy array, reversed

This function uses fancy indexing to reverse the ordering of the elements in the input array, and returns the reversed array. You cannot use the [::-1] notation, nor the built-in reversed method, or any other Python function or loops. You can use the list(), range(), and np.arange() functions, however, and only some or all of those (but again, no loops!).

Hint: Construct a list of indices and use NumPy fancy indexing to reverse the ordering of the elements in the input list, then return the reversed array.


In [ ]:


In [ ]:
import numpy as np
np.random.seed(5748)

x1 = np.random.random(75)
y1 = x1[::-1]  # Sorry, you're not allowed to do this!
np.testing.assert_allclose(y1, reverse_array(x1))

In [ ]:
np.random.seed(68382)

x2 = np.random.random(581)
y2 = x2[::-1]  # Sorry, you're not allowed to do this!
np.testing.assert_allclose(y2, reverse_array(x2))