7. Broadcasting
>> a = np.tile(np.arange(0, 40, 10), (3, 1)).T
>> a
array([[ 0, 0, 0],
[10, 10, 10],
[20, 20, 20],
[30, 30, 30]])
>> b = np.array([0, 1, 2])
>> a + b
array([[ 0, 1, 2],
[10, 11, 12],
[20, 21, 22],
[30, 31, 32]])
>> a = np.ones((4, 5))
>> a[0] = 2 # we assign an array of dimension 0 to an array of dimension 1
>> a
array([[2., 2., 2., 2., 2.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
A useful trick:
>> a = np.arange(0, 40, 10)
>> a.shape
(4,)
>> a = a[:, np.newaxis] # adds a new axis -> 2D array
>> a.shape
(4, 1)
>> a
array([[ 0],
[10],
[20],
[30]])
>> a + b
array([[ 0, 1, 2],
[10, 11, 12],
[20, 21, 22],
[30, 31, 32]])
Worked Example: Broadcasting
>> mileposts = np.array([0, 198, 303, 736, 871, 1175, 1475, 1544,
1913, 2448])
>> distance_array = np.abs(mileposts - mileposts[:, np.newaxis])
>> distance_array
array([[ 0, 198, 303, 736, 871, 1175, 1475, 1544, 1913, 2448],
[ 198, 0, 105, 538, 673, 977, 1277, 1346, 1715, 2250],
[ 303, 105, 0, 433, 568, 872, 1172, 1241, 1610, 2145],
[ 736, 538, 433, 0, 135, 439, 739, 808, 1177, 1712],
[ 871, 673, 568, 135, 0, 304, 604, 673, 1042, 1577],
[1175, 977, 872, 439, 304, 0, 300, 369, 738, 1273],
[1475, 1277, 1172, 739, 604, 300, 0, 69, 438, 973],
[1544, 1346, 1241, 808, 673, 369, 69, 0, 369, 904],
[1913, 1715, 1610, 1177, 1042, 738, 438, 369, 0, 535],
[2448, 2250, 2145, 1712, 1577, 1273, 973, 904, 535, 0]])
>> x, y = np.arange(5), np.arange(5)[:, np.newaxis]
>> distance = np.sqrt(x ** 2 + y ** 2)
>> distance
array([[0. , 1. , 2. , 3. , 4. ],
[1. , 1.41421356, 2.23606798, 3.16227766, 4.12310563],
[2. , 2.23606798, 2.82842712, 3.60555128, 4.47213595],
[3. , 3.16227766, 3.60555128, 4.24264069, 5. ],
[4. , 4.12310563, 4.47213595, 5. , 5.65685425]])
>> plt.pcolor(distance)
>> plt.colorbar()
Remark : the numpy.ogrid() function allows to directly create vectors x and y of the previous example, with two “significant dimensions”:
>> x, y = np.ogrid[0:5, 0:5]
>> x, y
(array([[0],
[1],
[2],
[3],
[4]]),
array([[0, 1, 2, 3, 4]]))
>> x.shape, y.shape
((5, 1), (1, 5))
>> distance = np.sqrt(x ** 2 + y ** 2)
>> x, y = np.mgrid[0:4, 0:4]
>> x
>> y
array([[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]])
8. Array shape manipulation
Flattening
>> a = np.array([[1, 2, 3], [4, 5, 6]])
>> a.ravel()
array([1, 2, 3, 4, 5, 6])
>> a.T
array([[1, 4],
[2, 5],
[3, 6]])
>> a.T.ravel()
array([1, 4, 2, 5, 3, 6])
Reshaping
>> a.shape
(2, 3)
>> b = a.ravel()
>> b = b.reshape((2, 3))
>> b
array([[1, 2, 3],
[4, 5, 6]])
>> a.reshape((2, -1)) # unspecified (-1) value is inferred
array([[1, 2, 3],
[4, 5, 6]])
ndarray.reshape may return a view (cf help(np.reshape))), or copy
>> b[0, 0] = 99
>> a
array([[99, 2, 3],
[ 4, 5, 6]])
>> a = np.zeros((3,2))
>> b = a.T.reshape(3*2)
>> b[0] = 9
>> a
array([[0., 0.],
[0., 0.],
[0., 0.]])
Adding a dimension
>> z = np.array([1, 2, 3])
>> z
array([1, 2, 3])
>> z[:, np.newaxis]
array([[1],
[2],
[3]])
>> z[np.newaxis, :]
array([[1, 2, 3]])
Dimension shuffling
>> a = np.arange(4*3*2).reshape(4, 3, 2)
>> a.shape
(4, 3, 2)
>> a[0, 2, 1]
5
>> b = a.transpose(1, 2, 0)
>> b.shape
(3, 2, 4)
>> b[2, 1, 0]
5
>> b[2, 1, 0] = -1
>> a[0, 2, 1]
-1
Resizing
>> a = np.arange(4)
>> a.resize((8,))
>> a
array([0, 1, 2, 3, 0, 0, 0, 0])
>> b = a # a.resize((4,))
Exercise: Shape manipulations
Look at the docstring for reshape, especially the notes section which has some more information about copies and views.
Use flatten as an alternative to ravel. What is the difference? (Hint: check which one returns a view and which a copy)
Experiment with transpose for dimension shuffling.
9. Sorting data
>> a = np.array([[4, 3, 5], [1, 2, 1]])
>> b = np.sort(a, axis=1)
>> b
array([[3, 4, 5],
[1, 1, 2]])
>> a.sort(axis=1)
>> a
array([[3, 4, 5],
[1, 1, 2]])
>> a = np.array([4, 3, 1, 2])
>> j = np.argsort(a)
>> j
>> a[j]
array([1, 2, 3, 4])
>> a = np.array([4, 3, 1, 2])
>> j_max = np.argmax(a)
>> j_min = np.argmin(a)
>> j_max, j_min
(0, 2)
Exercise: Sorting
Try both in-place and out-of-place sorting.
Try creating arrays with different dtypes and sorting them.
Use all or array_equal to check the results.
Look at np.random.shuffle for a way to create sortable input quicker.
Combine ravel, sort and reshape.
Look at the axis keyword for sort and rewrite the previous exercise.