import numpy as np
print("numpy: ", np.__version__)
numpy: 1.23.5
\(~\)
\(~\)
import numpy as np
print("numpy: ", np.__version__)
numpy: 1.23.5
show_array()
show_array_aggregation()
= np.array([[1, 2], [3, 4], [5, 6]])
data data
array([[1, 2],
[3, 4],
[5, 6]])
type(data)
numpy.ndarray
data.ndim
2
data.shape
(3, 2)
data.size
6
data.dtype
dtype('int64')
data.nbytes
48
= np.array([1, 2, 3], dtype=int)
d0 d0
array([1, 2, 3])
= np.array([1, 2, 3], dtype=float)
d1 d1
array([1., 2., 3.])
= np.array([1, 2, 3], dtype=complex)
d2 d2
array([1.+0.j, 2.+0.j, 3.+0.j])
= np.array([1, 2, 3], dtype=float)
data data
array([1., 2., 3.])
= np.array(data, dtype=int)
data data
array([1, 2, 3])
= np.array([1.6, 2, 3], dtype=float)
data int) data.astype(
array([1, 2, 3])
= np.array([1, 2, 3], dtype=float)
d1 = np.array([1, 2, 3], dtype=complex) d2
+ d2 d1
array([2.+0.j, 4.+0.j, 6.+0.j])
+ d2).dtype (d1
dtype('complex128')
-1, 0, 1])) np.sqrt(np.array([
/var/folders/4x/8kn2nym12cn7x7qmg_6s4b8h0000gn/T/ipykernel_80204/208196152.py:1: RuntimeWarning: invalid value encountered in sqrt
np.sqrt(np.array([-1, 0, 1]))
array([nan, 0., 1.])
-1, 0, 1], dtype=complex)) np.sqrt(np.array([
array([0.+1.j, 0.+0.j, 1.+0.j])
= np.array([1, 2, 3], dtype=complex)
data data
array([1.+0.j, 2.+0.j, 3.+0.j])
data.real
array([1., 2., 3.])
data.imag
array([0., 0., 0.])
np.real(data)
array([1., 2., 3.])
np.imag(data)
array([0., 0., 0.])
Multidimensional arrays are stored as contiguous data in memory. \(~\)Consider the case of a two-dimensional array, \(~\)containing rows and columns: \(~\)One possible way to store this array as a consecutive sequence of values is to store the rows after each other, and another equally valid approach is to store the columns one after another
The former is called row-major format and the latter is column-major format. Whether to use row-major or column-major is a matter of conventions, and the row-major format is used for example in the C programming language, and Fortran uses the column-major format
A numpy
array can be specified to be stored in row-major format, using the keyword argument order='C'
, and column-major format, using the keyword argument order='F'
, when the array is created or reshaped. The default format is row-major
In general, the numpy
array attribute ndarray.strides
defines exactly how this mapping is done. The strides
attribute is a tuple of the same length as the number of axes (dimensions) of the array. Each value in strides
is the factor by which the index for the corresponding axis is multiplied when calculating the memory offset (in bytes) for a given index expression
= np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int32)
data data
array([[1, 2, 3],
[4, 5, 6]], dtype=int32)
data.strides
(12, 4)
= np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int32, order='F')
data data
array([[1, 2, 3],
[4, 5, 6]], dtype=int32)
data.strides
(4, 8)
= np.array([1, 2, 3, 4])
data data.ndim, data.shape
(1, (4,))
= np.array(((1, 2), (3, 4)))
data data.ndim, data.shape
(2, (2, 2))
2, 3)) np.zeros((
array([[0., 0., 0.],
[0., 0., 0.]])
= np.ones(4)
data data, data.dtype
(array([1., 1., 1., 1.]), dtype('float64'))
5.4 * np.ones(10)
array([5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4])
10, 5.4) # slightly more efficient np.full(
array([5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4])
= np.empty(5)
x1 3.0)
x1.fill( x1
array([3., 3., 3., 3., 3.])
0, 11, 1) np.arange(
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
0, 10, 11) # generally recommended np.linspace(
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])
0, 2, 10) # 5 data points between 10**0=1 to 10**2=100 np.logspace(
array([ 1. , 1.66810054, 2.7825594 , 4.64158883,
7.74263683, 12.91549665, 21.5443469 , 35.93813664,
59.94842503, 100. ])
= np.array([-1, 0, 1])
x = np.array([-2, 0, 2])
y
= np.meshgrid(x, y) X, Y
X
array([[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]])
Y
array([[-2, -2, -2],
[ 0, 0, 0],
[ 2, 2, 2]])
= (X + Y)**2
Z Z
array([[9, 4, 1],
[1, 0, 1],
[1, 4, 9]])
3, dtype=float) np.empty(
array([0., 0., 0.])
def f(x):
= np.ones_like(x) # compute with x and y
y return y
= np.array([[1, 2, 3], [4, 5, 6]])
x = f(x)
y y
array([[1, 1, 1],
[1, 1, 1]])
4) np.identity(
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
4, k=1) np.eye(
array([[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.],
[0., 0., 0., 0.]])
4, k=-1) np.eye(
array([[0., 0., 0., 0.],
[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])
0, 20, 5)) np.diag(np.arange(
array([[ 0, 0, 0, 0],
[ 0, 5, 0, 0],
[ 0, 0, 10, 0],
[ 0, 0, 0, 15]])
= np.arange(0, 11)
a a
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
0] a[
0
-1] a[
10
4] a[
4
1:-1] a[
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
1:-1:2] a[
array([1, 3, 5, 7, 9])
5] a[:
array([0, 1, 2, 3, 4])
-5:] a[
array([ 6, 7, 8, 9, 10])
-2] a[::
array([10, 8, 6, 4, 2, 0])
= lambda m, n: n + 10*m f
# please search for numpy.fromfunction at google
= np.fromfunction(f, (6, 6), dtype=int)
A A
array([[ 0, 1, 2, 3, 4, 5],
[10, 11, 12, 13, 14, 15],
[20, 21, 22, 23, 24, 25],
[30, 31, 32, 33, 34, 35],
[40, 41, 42, 43, 44, 45],
[50, 51, 52, 53, 54, 55]])
1] # the second column A[:,
array([ 1, 11, 21, 31, 41, 51])
1, :] # the second row A[
array([10, 11, 12, 13, 14, 15])
3, :3] A[:
array([[ 0, 1, 2],
[10, 11, 12],
[20, 21, 22]])
3:, :3] A[
array([[30, 31, 32],
[40, 41, 42],
[50, 51, 52]])
2, ::2] A[::
array([[ 0, 2, 4],
[20, 22, 24],
[40, 42, 44]])
1::2, 1::3] A[
array([[11, 14],
[31, 34],
[51, 54]])
Subarrays that are extracted from arrays using slice operations are alternative views of the same underlying array data. That is, \(~\)they are arrays that refer to the same data in memory as the original array, \(~\)but with a different strides
configuration
When elements in a view are assigned new values, \(~\)the values of the original array are therefore also updated. For example,
= A[1:5, 1:5]
B B
array([[11, 12, 13, 14],
[21, 22, 23, 24],
[31, 32, 33, 34],
[41, 42, 43, 44]])
= 0
B[:, :] A
array([[ 0, 1, 2, 3, 4, 5],
[10, 0, 0, 0, 0, 15],
[20, 0, 0, 0, 0, 25],
[30, 0, 0, 0, 0, 35],
[40, 0, 0, 0, 0, 45],
[50, 51, 52, 53, 54, 55]])
copy
method of the ndarray
instance= B[1:3, 1:3].copy()
C C
array([[0, 0],
[0, 0]])
= 1
C[:, :] C
array([[1, 1],
[1, 1]])
B
array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
= np.linspace(0, 1, 11)
A A
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
0, 2, 4])] A[np.array([
array([0. , 0.2, 0.4])
0, 2, 4]] A[[
array([0. , 0.2, 0.4])
> 0.5 A
array([False, False, False, False, False, False, True, True, True,
True, True])
> 0.5] A[A
array([0.6, 0.7, 0.8, 0.9, 1. ])
= np.arange(10)
A = [2, 4, 6] indices
= A[indices] B
0] = -1
B[ A
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
= -1
A[indices] A
array([ 0, 1, -1, 3, -1, 5, -1, 7, 8, 9])
= np.arange(10) A
= A[A > 5] B
0] = -1
B[ A
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
> 5] = -1
A[A A
array([ 0, 1, 2, 3, 4, 5, -1, -1, -1, -1])
4, 4), ':, :') show_array((
4, 4), '0') show_array((
4, 4), '1, :') show_array((
4, 4), ':, 2') show_array((
4, 4), '0:2, 0:2') show_array((
4, 4), '0:2, 2:4') show_array((
4, 4), '::2, ::2') show_array((
4, 4), '1::2, 1::2') show_array((
4, 4), ':, [0, 3]') show_array((
4, 4), '[1, 3], [0, 3]') show_array((
4, 4), ':, [False, True, True, False]') show_array((
4, 4), '1:3, [False, True, True, False]') show_array((
= np.array([[1, 2], [3, 4]])
data = np.reshape(data, (1, 4))
data1 data1
array([[1, 2, 3, 4]])
0, 1] = -1
data1[ data
array([[ 1, -1],
[ 3, 4]])
= data.reshape(4)
data2 data2
array([ 1, -1, 3, 4])
1] = -2
data2[ data
array([[ 1, -2],
[ 3, 4]])
= np.array([[1, 2], [3, 4]])
data = np.ravel(data)
data1 data1
array([1, 2, 3, 4])
0] = -1
data1[ data
array([[-1, 2],
[ 3, 4]])
ndarray
method flatten
perform the same function, \(~\)but returns a copy instead of a view= data.flatten()
data2 data2
array([-1, 2, 3, 4])
0] = -2
data2[ data
array([[-1, 2],
[ 3, 4]])
= np.arange(0, 5)
data data.shape
(5,)
= data[:, np.newaxis]
column column
array([[0],
[1],
[2],
[3],
[4]])
column.shape
(5, 1)
= data[np.newaxis, :]
row row
array([[0, 1, 2, 3, 4]])
row.shape
(1, 5)
0, 0] = -1
row[ data
array([-1, 1, 2, 3, 4])
=1) np.expand_dims(data, axis
array([[-1],
[ 1],
[ 2],
[ 3],
[ 4]])
= np.expand_dims(data, axis=0)
row row
array([[-1, 1, 2, 3, 4]])
0, 0] = 0
row[ data
array([0, 1, 2, 3, 4])
= np.arange(5)
data data
array([0, 1, 2, 3, 4])
np.vstack((data, data, data))
array([[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]])
np.hstack((data, data, data))
array([0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4])
= data[:, np.newaxis]
data data.shape
(5, 1)
np.hstack((data, data, data))
array([[0, 0, 0],
[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4]])
= np.array([[1, 2], [3, 4]])
data1 = np.array([[5, 6]]) data2
=0) np.concatenate((data1, data2), axis
array([[1, 2],
[3, 4],
[5, 6]])
=1) np.concatenate((data1, data2.T), axis
array([[1, 2, 5],
[3, 4, 6]])
= np.array([[1, 2], [3, 4]])
x = np.array([[5, 6], [7, 8]]) y
+ y x
array([[ 6, 8],
[10, 12]])
- x y
array([[4, 4],
[4, 4]])
* y x
array([[ 5, 12],
[21, 32]])
/ x y
array([[5. , 3. ],
[2.33333333, 2. ]])
* 2 x
array([[2, 4],
[6, 8]])
2**x
array([[ 2, 4],
[ 8, 16]])
/ 2 y
array([[2.5, 3. ],
[3.5, 4. ]])
/ 2).dtype (y
dtype('float64')
= np.array([[11, 12, 13], [21, 22, 23], [31, 32, 33]])
a = np.array([[1, 2, 3]]) b
+ b a
array([[12, 14, 16],
[22, 24, 26],
[32, 34, 36]])
show_array_broadcasting(a, b)
+ b.T a
array([[12, 13, 14],
[23, 24, 25],
[34, 35, 36]])
show_array_broadcasting(a, b.T)
= np.array([1, 2, 3, 4]).reshape(2, 2)
x x.shape
(2, 2)
= np.array([[2, 4]])
z z.shape
(1, 2)
/ z x
array([[0.5, 0.5],
[1.5, 1. ]])
= np.vstack((z, z))
zz zz
array([[2, 4],
[2, 4]])
/ zz x
array([[0.5, 0.5],
[1.5, 1. ]])
= np.array([[2], [4]])
z z.shape
(2, 1)
/ z x
array([[0.5 , 1. ],
[0.75, 1. ]])
= np.concatenate([z, z], axis=1)
zz zz
array([[2, 2],
[4, 4]])
/ zz x
array([[0.5 , 1. ],
[0.75, 1. ]])
= z = np.array([1, 2, 3, 4])
x = np.array([5, 6, 7, 8])
y = x + y # x is reassigned to a new array x
x, z
(array([ 6, 8, 10, 12]), array([1, 2, 3, 4]))
= z = np.array([1, 2, 3, 4])
x = np.array([5, 6, 7, 8])
y += y # the values of array x are updated in place x
x, z
(array([ 6, 8, 10, 12]), array([ 6, 8, 10, 12]))
= np.linspace(-1, 1, 11)
x x
array([-1. , -0.8, -0.6, -0.4, -0.2, 0. , 0.2, 0.4, 0.6, 0.8, 1. ])
= np.sin(np.pi * x) y
round(y, decimals=4) np.
array([-0. , -0.5878, -0.9511, -0.9511, -0.5878, 0. , 0.5878,
0.9511, 0.9511, 0.5878, 0. ])
**2, np.cos(x)**2) np.add(np.sin(x)
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
**2 + np.cos(x)**2 np.sin(x)
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
def heaviside(x):
return 1 if x > 0 else 0
-1) heaviside(
0
1.5) heaviside(
1
```{python}
x = np.linspace(-5, 5, 11)
heaviside(x)
```
ValueError
1 x = np.linspace(-5, 5, 11)
----> 2 heaviside(x)
1 def heaviside(x):
----> 2 return 1 if x > 0 else 0
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
= np.vectorize(heaviside)
heaviside heaviside(x)
array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1])
def heaviside(x): # much better way
return 1 * (x > 0)
heaviside(x)
array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1])
= np.random.normal(size=(15, 15)) data
np.mean(data)
0.023241194956263422
data.mean()
0.023241194956263422
= np.random.normal(size=(5, 10, 15)) data
sum(axis=0).shape data.
(10, 15)
sum(axis=(0, 2)).shape data.
(10,)
sum() data.
-10.634656118697123
= np.arange(9).reshape(3, 3)
data data
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
sum() data.
36
None) show_array_aggregation(data,
sum(axis=0) data.
array([ 9, 12, 15])
0) show_array_aggregation(data,
sum(axis=1) data.
array([ 3, 12, 21])
1) show_array_aggregation(data,
= np.array([1, 2, 3, 4])
a = np.array([4, 3, 2, 1]) b
< b a
array([ True, True, False, False])
all(a < b) np.
False
any(a < b) np.
True
= np.array([-2, -1, 0, 1, 2]) x
> 0 x
array([False, False, False, True, True])
1 * (x > 0)
array([0, 0, 0, 1, 1])
* (x > 0) x
array([0, 0, 0, 1, 2])
def pulse(x, position, height, width):
return height * (x >= position) * (x <= (position + width))
= np.linspace(-5, 5, 31) x
=-2, height=1, width=5) pulse(x, position
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 0, 0, 0, 0, 0, 0])
=1, height=2, width=2) pulse(x, position
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
2, 2, 2, 0, 0, 0, 0, 0, 0])
= np.linspace(-4, 4, 9)
x x
array([-4., -3., -2., -1., 0., 1., 2., 3., 4.])
< 0, x**2, x**3) np.where(x
array([16., 9., 4., 1., 0., 1., 8., 27., 64.])
< -1, x < 2, x>= 2], [x**2, x**3, x**4]) np.select([x
array([ 16., 9., 4., -1., 0., 1., 16., 81., 256.])
0, 0, 0, 1, 1, 1, 2, 2, 2], [x**2, x**3, x**4]) np.choose([
array([ 16., 9., 4., -1., 0., 1., 16., 81., 256.])
abs(x) > 2] x[np.
array([-4., -3., 3., 4.])
= np.unique([1, 2, 3, 3])
a a
array([1, 2, 3])
= np.unique([2, 3, 4, 4, 5, 6, 5])
b b
array([2, 3, 4, 5, 6])
np.in1d(a, b)
array([False, True, True])
1 in a, 1 in b
(True, False)
all(np.in1d(a, b)) # to test if a is a subset of b np.
False
np.union1d(a, b)
array([1, 2, 3, 4, 5, 6])
np.intersect1d(a, b)
array([2, 3])
np.setdiff1d(a, b)
array([1])
np.setdiff1d(b, a)
array([4, 5, 6])
= np.arange(9).reshape(3, 3)
data data
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
np.transpose(data)
array([[0, 3, 6],
[1, 4, 7],
[2, 5, 8]])
= np.random.randn(1, 2, 3, 4, 5) data
data.shape
(1, 2, 3, 4, 5)
data.T.shape
(5, 4, 3, 2, 1)
= np.arange(1, 7).reshape(2, 3)
A A
array([[1, 2, 3],
[4, 5, 6]])
= np.arange(1, 7).reshape(3, 2)
B B
array([[1, 2],
[3, 4],
[5, 6]])
np.dot(A, B)
array([[22, 28],
[49, 64]])
np.dot(B, A)
array([[ 9, 12, 15],
[19, 26, 33],
[29, 40, 51]])
@ B # python 3.5 above A
array([[22, 28],
[49, 64]])
@ A B
array([[ 9, 12, 15],
[19, 26, 33],
[29, 40, 51]])
= np.arange(9).reshape(3, 3)
A A
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
= np.arange(3)
x x
array([0, 1, 2])
np.dot(A, x)
array([ 5, 14, 23])
A.dot(x)
array([ 5, 14, 23])
@ x A
array([ 5, 14, 23])
= np.random.rand(3, 3)
A = np.random.rand(3, 3) B
= np.dot(B, np.dot(A, np.linalg.inv(B))) Ap
= B.dot(A.dot(np.linalg.inv(B))) Ap
@ A @ np.linalg.inv(B) B
array([[-1.61214636, 1.61125853, 3.42494674],
[ 1.13023345, 1.12540233, -0.22132674],
[-1.17524723, 1.02348252, 2.29795188]])
np.inner(x, x)
5
np.dot(x, x)
5
= x[:, np.newaxis]
y y
array([[0],
[1],
[2]])
np.dot(y.T, y)
array([[5]])
\[\begin{pmatrix} a_0 b_0 & a_0b_1 & \cdots & a_0 b_N \\ a_1 b_0 & \cdots & \cdots & a_1 b_N \\ \vdots & \ddots & & \vdots \\ a_M b_0 & & \ddots & a_M b_N \\ \end{pmatrix} \]
= np.array([1, 2, 3]) x
np.outer(x, x)
array([[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
np.kron(x, x)
array([1, 2, 3, 2, 4, 6, 3, 6, 9])
np.kron(x[:, np.newaxis], x[np.newaxis, :])
array([[1, 2, 3],
[2, 4, 6],
[3, 6, 9]])
2, 2)), np.identity(2)) np.kron(np.ones((
array([[1., 0., 1., 0.],
[0., 1., 0., 1.],
[1., 0., 1., 0.],
[0., 1., 0., 1.]])
2), np.ones((2, 2))) np.kron(np.identity(
array([[1., 1., 0., 0.],
[1., 1., 0., 0.],
[0., 0., 1., 1.],
[0., 0., 1., 1.]])
= np.array([1, 2, 3, 4])
x = np.array([5, 6, 7, 8]) y
"n,n", x, y) np.einsum(
70
np.inner(x, y)
70
= np.arange(9).reshape(3, 3)
A = A.T B
"mk,kn", A, B) np.einsum(
array([[ 5, 14, 23],
[ 14, 50, 86],
[ 23, 86, 149]])
"mk,kn", A, B) == np.dot(A, B)) np.alltrue(np.einsum(
True