Numpy provides us with multi-dimensional array objects which is useful for scientific computing. In numpy:
[1,2,3] is a numpy object of rank 1 and shape 3
[[1,2], [4,5], [7,8]] is a numpy object of rank 3 and shape 2.
The following provides different ways of creating numpy objects.
import numpy as np
a = np.array([1,2,3])
print(a)
print(a.shape)
b = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print(b)
print(b.shape)
c = np.array([[1, 2, 3]]) # Note the extra []
print(c.shape)
Numpy supports far more numerical types (15) compared to standard Python. We have int8, int16, int32, int64 data types in integer and float16, float32, float64 data types in float. The dtype command can be used to determine the data type.
a = np.array([8, 10, 12])
print(a.dtype)
a1 = np.array([8.0, 10, 12])
print(a1.dtype)
Similar to lists, the numpy array indices start from zero. For multi-dimensional arrays, the way you access the elements is different.
a = np.array([8, 10, 12])
a[1] = 11
print(a)
b = np.array([[8, 10, 12], [20, 22, 24]])
b[0,1] = 11
print(b)
print(b[0,1])
print(b[0])
c = np.array([[8, 10, 12]])
print(c[0,1]) #Note the difference
In numpy, there are several functions available to create standard arrays.
c = np.zeros((2,3)) #Creates a (2,3) array of all zeros
print(c)
d = np.ones((2,3)) #Creates a (2,3) array of all ones
print(d)
e = np.eye(3) # Creates a (3,3) identity matrix
print(e)
a = np.random.random((3,3)) # Creats a (3,3) matrix of random numbers
print(a)
The arange() function is similar to range() function in lists. The reshape() and flatten() are other useful commands to adjust array dimensions.
a = np.arange(10)
print(a)
There are several ways to apply the same function to numpy arrays. We will demonstrate that with reshape function below.
b = np.reshape(a, (2,5))
print(b)
c = a.reshape(2,5)
print(c)
d = b.flatten()
print(d)
f = np.arange(20).reshape(4,5)
print(f)
Transpose switches the shape along dimensions. When you have more than two dimensions, need to specify a list of axis permutations. There are multiple ways to apply the transpose command.
a = np.arange(10).reshape((2,5))
print(a)
b = np.transpose(a)
print(b)
c = a.transpose()
print(c)
d = a.T
print(d)
Subarrays can be created using array[start:stop:step size] format. Note that the sub arrays are created only until the stop-1 index. Any of start, stop, or step size can be left out.
a = np.arange(10)
print(a[3:])
print(a[:2])
print(a[2:8:2])
print(a[3::-1])
Multi-dimensional slicing can be done using array[row slice, column slice] format.
a = np.arange(12)
b = a.reshape(3,4)
print(b[1,:]) # prints second row
print(b[:,1:3]) # prints second, and third column
Slicing returns views and not copies. Use copy() command to create separate copies. Observe carefully the output of the following codes.
a = np.arange(12)
b = a.reshape(3,4)
print("b=", b)
c = b # using assignment operator
d = b[1,:] # using slicing
e = b.copy() # using the copy command
b[1,0] = 14
print("b=", b)
print("c=", c)
print("d=", d)
print("e=", e)
Observe carefully the output of the following codes.
a = np.arange(12)
b = a.reshape(3,4)
print("b=", b)
c = b # using assignment operator
d = b[1,:] # using slicing
e = b.copy() # using the copy command
c[1,0] = 15
print("b=", b)
print("c=", c)
print("d=", d)
print("e=", e)
Concatenate function can be used to expand the array along various dimensions. The axis parameter controls the direction of concatenation with default axis = 0. Other useful commands are append, vstack, hstack, dstack, tile. Observe carefully the output of these codes.
a = np.arange(6).reshape((2,3))
print("a = " , a)
print("a.shape = ", a.shape)
b = np.array([[4,5]])
print("b.shape = ", b.shape)
c = np.array([[6,7,8]])
print("c.shape = ", c.shape)
d = np.concatenate((a,b.T), axis=1)
print("d = ", d)
e = np.concatenate((a,c))
print(e)
Note that in numpy, the traditional mathematical operations happen element wise and are not matrix operations like in matlab.
g = np.array([[1,2,3],[4,5,6],[7,8,9]])
h = np.array([[21,22,23],[24,25,26],[27,28,29]])
h+g
h-g
h*g
h/g
Use the dot function for matrix multiplication for two dimensional arrays. The dot function serves as inner product for single dimensional arrays. Note the difference between dot product and multiplication.
i = np.ones((3,3))
j = np.array([1,2,3])
print(i*j)
print(i.dot(j))
When array dimensions do not match, python often expands the dimensions of the smaller array. This is called broadcasting. Check Python broadcasting rules if this feature is useful. Observe carefully the output of the following codes.
a = np.array([1,2,3])
b = np.array([5])
print(a+b)
a = np.array([[1,2,3],[11, 12, 13], [21, 22, 23]])
b = np.array([1, 0 , 0])
print(a + b) # 1 is added to first column
Numpy offers several useful mathematical functions.
a = np.array([[1,2],[3,4]])
a.sum()
a.mean()
a.sum(axis=1)
print(np.sqrt(a))
The biggest advantage of numpy is vectorization which enables you to write compact codes which may also be computationally efficient. Let us say your goal is to determine the following sum
$$ t = \sum_{x=0}^{10} 0.1x e^{0.1x} $$
import math as mt
t = 0.0
for x in range(11):
t = t + 0.1*x*mt.exp(0.1*x)
print(t)
The above code can be written without for loop as follows.
import math as mt
x = np.arange(0,1.1,0.1)
t = np.sum(x*np.exp(x))
print(t)
For more on numpy, refer to the official numpy tutorial here