NumPy’s main object is an homogeneous multidimensional array:
Numpy’s array class is called ndarray
. It is also known by the alias array
.
Warning : numpy.array
is not the same as the Standard Python Library class array.array
.
It is very common to alias numpy
into np
when importing.
import numpy as np
print(np)
<module 'numpy' from '/root/.cache/pypoetry/virtualenvs/pyplot-doc-VOfsvtlq-py3.11/lib/python3.11/site-packages/numpy/__init__.py'>
The coordinates of a point in 3D space is an array of rank 1, because it has one axis. That axis has a length of 3.
point = np.array([1, 2, 1])
print(point)
print()
print(type(point))
print(point.ndim, point.shape) # the rank, and size of each axe (dimension)
print(point.size, point.dtype) # total number of elements, and kind of elements.
print()
print(point[0], point[1], point[2])
[1 2 1] <class 'numpy.ndarray'> 1 (3,) 3 int64 1 2 1
The array below has rank 2 (it is 2-dimensional):
point = np.array([[ 1., 0., 0.],
[ 0., 1., 2.]])
print(point)
print()
print(type(point))
print(point.ndim, point.shape) # the rank, and size of each axe (dimension)
print(point.size, point.dtype) # total number of elements, and kind of elements.
print()
print(point[0, 0], point[0, 1], point[0, 2])
print(point[1, 0], point[1, 1], point[1, 2])
[[1. 0. 0.] [0. 1. 2.]] <class 'numpy.ndarray'> 2 (2, 3) 6 float64 1.0 0.0 0.0 0.0 1.0 2.0
Few other ways to create NumPy arrays:
np.zeros((3,4)) # create a matrix (3,4) and init with zeroes
array([[0., 0., 0., 0.], [0., 0., 0., 0.], [0., 0., 0., 0.]])
np.ones((2,3,4), dtype=np.int16) # create a matrix (2,3,4) and init with ones
array([[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]], [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]], dtype=int16)
np.arange( 10, 30, 5 ) # create a 1D array and init with a uniform
# sequence of numbers (10…30, every 5)
array([10, 15, 20, 25])
np.linspace( 0, 2, 9 ) # create a 1D array and init with a linear
# sequence of 9 numbers (0…2)
array([0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])
Arithmetic operators on arrays apply elementwise. A new array is created and filled with the result.
a = np.array( [20, 30, 40, 50] )
b = np.arange( 4 )
print(a)
print(b)
[20 30 40 50] [0 1 2 3]
a-b
array([20, 29, 38, 47])
b**2
array([0, 1, 4, 9])
10*np.sin(a)
array([ 9.12945251, -9.88031624, 7.4511316 , -2.62374854])
a<35
array([ True, True, False, False])
Let's try with 2D operations.
a = np.array( [[1,1], [0,1]] )
b = np.array( [[2,0], [3,4]] )
print(a)
print(b)
[[1 1] [0 1]] [[2 0] [3 4]]
a*b # elementwise product
array([[2, 0], [0, 4]])
a.dot(b) # matrix product
array([[5, 4], [3, 4]])
np.dot(a,b) # another matrix product
array([[5, 4], [3, 4]])
print(a.sum())
print(a.min())
print(a.max())
3 0 1
np.exp(b)
array([[ 7.3890561 , 1. ], [20.08553692, 54.59815003]])
np.sqrt(b)
array([[1.41421356, 0. ], [1.73205081, 2. ]])
c = np.array( [[1, 1, 2], [0, 1, 2]] )
a+c # a & c must have a compatible shape
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[20], line 2 1 c = np.array( [[1, 1, 2], [0, 1, 2]] ) ----> 2 a+c # a & c must have a compatible shape ValueError: operands could not be broadcast together with shapes (2,2) (2,3)
Transposing a 1D vector to make it columnar:
row = np.arange(3)
print(row)
column = row[:, np.newaxis]
print(column)
[0 1 2] [[0] [1] [2]]
Any mathematical expression using a row and a column will create a 2D matrix:
row+column
array([[0, 1, 2], [1, 2, 3], [2, 3, 4]])
np.exp(row)*np.exp(column)
array([[ 1. , 2.71828183, 7.3890561 ], [ 2.71828183, 7.3890561 , 20.08553692], [ 7.3890561 , 20.08553692, 54.59815003]])
The logical operators applied to N-array produce an N-array of booleans.
mat = np.arange(3*2).reshape(3, 2)
print(mat)
cond = mat<3
print(cond)
[[0 1] [2 3] [4 5]] [[ True True] [ True False] [False False]]
Because False
is interpreted as 0
when involved in a numerical operation, an ndarray
of booleans can be used to set to 0
elements of another matrix.
x = np.random.rand(3, 2)
print(x)
result = x*cond
print(result)
[[0.37058439 0.27492504] [0.59183055 0.61527709] [0.05840027 0.11723157]] [[0.37058439 0.27492504] [0.59183055 0. ] [0. 0. ]]
The numpy functions can also receive some scalar values and return scalar results:
def my_function(x):
return np.sin(np.exp(x))
my_function(np.arange(3))
array([0.84147098, 0.41078129, 0.89385495])
my_function(12.0)
0.991769422460002
Quite the same as for built-in sequences, one can use slices for read and write. Below, we extend a 2D array by adding null elements all around:
matrix = np.arange(6).reshape(2, 3)
print(matrix)
print()
ext_shape = np.array(matrix.shape)+2
ext_matrix = np.zeros(ext_shape)
print(ext_matrix)
print()
ext_matrix[1:-1, 1:-1] = matrix
print(ext_matrix)
[[0 1 2] [3 4 5]] [[0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.] [0. 0. 0. 0. 0.]] [[0. 0. 0. 0. 0.] [0. 0. 1. 2. 0.] [0. 3. 4. 5. 0.] [0. 0. 0. 0. 0.]]