Vectorization of Code
Vectorization of code is a strategy to get more compact code that is possibly executed
faster. The fundamental idea is to conduct an operation on or to apply a function to a
complex object “at once” and not by iterating over the single elements of the object. In
Python, the functional programming tools map, filter, and reduce provide means for
vectorization. In a sense, NumPy has vectorization built in deep down in its core.
Basic Vectorization
As we learned in the previous section, simple mathematical operations can be
implemented on numpy.ndarray objects directly. For example, we can add two NumPy
arrays element-wise as follows:
In [ 120 ]: r = np.random.standard_normal(( 4 , 3 ))
s = np.random.standard_normal(( 4 , 3 ))
In [ 121 ]: r + s
Out[121]: array([[-1.94801686, -0.6855251 , 2.28954806],
[ 0.33847593, -1.97109602, 1.30071653],
[-1.12066585, 0.22234207, -2.73940339],
[ 0.43787363, 0.52938941, -1.38467623]])
NumPy also supports what is called broadcasting. This allows us to combine objects of
different shape within a single operation. We have already made use of this before.
Consider the following example:
In [ 122 ]: 2 * r + 3
Out[122]: array([[ 2.54691692, 1.65823523, 8.14636725],
[ 4.94758114, 0.25648128, 1.89566919],
[ 0.41775907, 0.58038395, 2.06567484],
[ 0.67600205, 3.41004636, 1.07282384]])
In this case, the r object is multiplied by 2 element-wise and then 3 is added element-wise
— the 3 is broadcasted or stretched to the shape of the r object. It works with differently
shaped arrays as well, up to a certain point:
In [ 123 ]: s = np.random.standard_normal( 3 )
r + s
Out[123]: array([[ 0.23324118, -1.09764268, 1.90412565],
[ 1.43357329, -1.79851966, -1.22122338],
[-0.83133775, -1.63656832, -1.13622055],
[-0.70221625, -0.22173711, -1.63264605]])
This broadcasts the one-dimensional array of size 3 to a shape of (4, 3). The same does not
work, for example, with a one-dimensional array of size 4:
In [ 124 ]: s = np.random.standard_normal( 4 )
r + s
Out[124]: ValueError
operands could not be broadcast together with shapes (4,3) (4,)
However, transposing the r object makes the operation work again. In the following code,
the transpose method transforms the ndarray object with shape (4, 3) into an object of
the same type with shape (3, 4):
In [ 125 ]: r.transpose() + s
Out[125]: array([[-0.63380522, 0.5964174 , 0.88641996, -0.86931849],
[-1.07814606, -1.74913253, 0.9677324 , 0.49770367],
[ 2.16591995, -0.92953858, 1.71037785, -0.67090759]])
In [ 126 ]: np.shape(r.T)
Out[126]: (3, 4)