This notebook aims to quickly walk you through the most fundamental bits of NumPy, including:
This notebook is created by cherry-picking from the official documents of NumPy. Please refer to that page for more information.
In [6]:
import numpy as np
NumPy’s main object is the homogeneous multidimensional array (ndarray
). It is a table of elements (usually numbers), all of the same type, indexed by a tuple of positive integers.
A list of elements can be expressed as an ndarray
of rank 1, i.e. a 1D array; a matrix can be expressed as an ndarray
of rank 2.
Here lists some important attributes of ndarray
:
ndarray.ndim
: the rank of the ndarray
. For instance, a matrix has a rank of 2.ndarray.shape
: the dimensions of the ndarray
as a tuple of integers. For an array having 10 elements, the shape is (10,)
(note the trailing comma, not the same as (10, 1)
); for a matrix having 20 rows and 30 columns, the shape is (20, 30)
.ndarray.size
: the total number of elements in the ndarray
, which is equal to the product of the dimensions.ndarray.dtype
: an object describing the type of the elements in the array.
In [7]:
arr = np.array(range(1, 10))
print('arr\t\t', arr)
print('arr.ndim\t', arr.ndim)
print('arr.shape\t', arr.shape)
print('arr.size\t', arr.size)
print('arr.dtype\t', arr.dtype)
There are several ways to create ndarray
s.
You can create a 1D ndarray
from an existing list/array easily using the array
function.
In [8]:
np.array([1, 2, 3, 4])
Out[8]:
Note that there is only one argument. So never do this:
In [9]:
# Do not do this
#np.array(1, 2, 3, 4)
To create a matrix, call array
on a sequence of sequence.
In [10]:
x = np.array([[1, 2], [3, 4], [5, 6]])
x
Out[10]:
In [11]:
x.shape
Out[11]:
When the contents of the array to be created are unknown, but its dimensions are known, use one of zeros
, ones
, empty
.
In [12]:
np.zeros((2, 3)) # the elements are explicitly initialized to zeros
Out[12]:
In [13]:
np.ones((2, 3)) # the elements are explicitly initialized to ones
Out[13]:
In [14]:
np.empty((2, 3)) # the elements are not explicitly initialized; expect random values
Out[14]:
The default dtype
is numpy.float64
for these functions.
Akin to range
in Python, arange
in NumPy returns a sequence of numbers in a ndarray
. Use the dtype
parameter to change the type, or use astype()
function to cast into another type.
In [15]:
np.arange(1, 3, 0.2)
Out[15]:
Due to the finite precision of floating point numbers, however, it's better to use linspace
when we are trying to create a sequence of floating point numbers, specifying how many elements we want, instead of the step
.
In [16]:
np.linspace(1, 3, 7)
Out[16]:
In [17]:
arr = np.arange(1, 10)
arr
Out[17]:
In [18]:
arr.shape
Out[18]:
In [19]:
arr.reshape((3, 3))
Out[19]:
The reshape
function returns a new ndarray
with the shape changed without modifying the original one.
In [20]:
arr
Out[20]:
In [21]:
arr.reshape((9,1))
Out[21]:
To directly modify the shape of an ndarray
:
In [22]:
arr.shape = (3, 3)
arr
Out[22]:
Note that 1d arrays and 2d arrays are different.
In [23]:
xx = arr.reshape((1,9))
xx
Out[23]:
In [24]:
xx.shape
Out[24]:
In [25]:
xx[0]
Out[25]:
In [26]:
arr
Out[26]:
In [27]:
arr.shape
Out[27]:
Arithmetic operators on ndarray
s apply elementwise (so the operation is vectorized). A new ndarray
will be created to hold the result.
In [28]:
arr = np.array([1, 2])
In [29]:
arr + 1
Out[29]:
In [30]:
arr * 2
Out[30]:
In [31]:
arr ** 2
Out[31]:
Given two ndarray
s with proper shapes:
In [32]:
a = np.array([1, 2])
a
Out[32]:
In [33]:
b = np.array([[1], [2]])
b
Out[33]:
To calculate the dot product, the sentence in the following cell is intuitive but WRONG:
In [34]:
a * b # calculating elementwise product!
Out[34]:
To correctly calculate the dot products of two ndarray
s, use numpy.dot
or the dot
function on the ndarray
object.
In [35]:
a.dot(b)
Out[35]:
In [36]:
np.dot(a, b)
Out[36]:
Both ways create a new ndarray
to hold the results without modifying the original ones.
See https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.norm.html for more details.
In [37]:
a = np.arange(3)-1
a
Out[37]:
In [38]:
np.linalg.norm(a)
Out[38]:
In [39]:
np.linalg.norm(a, ord=1)
Out[39]:
In [40]:
np.linalg.norm(a, ord=np.inf)
Out[40]:
Since Python 3.5, we can use the infix operator *
for element-wise multiplication, and the infix operator @
for matrix multiplication.
In [51]:
A = np.array([[1,2],[3,4]])
B = np.array([[-1,1],[2,1]])
print(np.matmul(A, B)) # preferred over np.dot()
print(A @ B) # A and B must be numpy arrays
print(A * B)
print(B @ A)
In [52]:
x = np.array([1, 2]).reshape((2,1))
print(A @ x)
To solve $\mathbf{A z = B}$, we have $\mathbf{z = A^{-1} B}$
In [54]:
z = np.linalg.inv(A) @ B
z
Out[54]:
In [56]:
A @ z
Out[56]:
In [ ]: