Very Basics
The basics
NumPy’s array class is called ndarray.
Properties:
ndarray.ndim: dimansions/axes of the arrary.
ndarray.shape: $(x, y, z, t, \cdots) : tuple?$
ndarray.size: the total number of elements of the array.
ndarray.dtype: ?
ndarray.itemsize: ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| >>> import numpy as np
>>> a = np.arange(15).reshape(3, 5)
>>> a
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
>>> a.shape
(3, 5)
>>> a.ndim
2
>>> a.dtype.name
'int64'
>>> a.itemsize
8
>>> a.size
15
>>> type(a)
<class 'numpy.ndarray'>
>>> b = np.array([6, 7, 8])
>>> b
array([6, 7, 8])
>>> type(b)
<class 'numpy.ndarray'>
|
Array creation
1
2
3
4
| >>> import numpy as np
>>> a = np.arrary([2, 3, 4])
>>> a
array([2, 3, 4])
|
- the type of the array can also be explicitly specified at creation time:
1
| >>> c = np.array([[1, 2], [3, 4]], dtype=np.complex128)
|
Often, the elements of an array are originally unknown, but its size is known. Hence, NumPy offers several functions to create arrays with initial placeholder content. These minimize the necessity of growing arrays, an expensive operation.
the function zeros() creates an array full of zeros, while ones() ones.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| >>> np.zeros((3, 4))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>> np.ones((2, 3, 4), dtype=np.int16)
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.empty((2, 3))
array([[3.73603959e-262, 6.02658058e-154, 6.55490914e-260], # may vary
[5.30498948e-313, 3.14673309e-307, 1.00000000e+000]])
|
- a sequence of numbers ($arange(m, n, step)([m,n))$):
1
2
| >>> np.arange(10, 30, 5)
array([10, 15, 20, 25])
|
linespace(begin, end, count)$[\text{begin},\space \text{end}]$
1
2
3
4
5
6
| x = np.linspace(0, 2, 10)
array(
[0. , 0.22222222, 0.44444444,
0.66666667, 0.88888889, 1.11111111,
1.33333333, 1.55555556, 1.77777778, 2. ]
)
|
Printing arrays
print(nparray)
Basic operations
Arithmetic operators on arrays apply elementwise. A new array is created and filled with the result.
elementwise product:
matrix product:
When operating with arrays of different types, the type of the resulting array corresponds to the more general or precise one (a behavior known as upcasting).
Universal functions
NumPy provides familiar mathematical functions such as $\sin,\space\cos$, and $\text{exp}$. In NumPy, these are called “universal functions”(ufunc). Within NumPy, these functions operate elementwise on an array, producing an array as output.
1
2
3
4
5
| >>> B = np.arange(3)
>>> B
array([0, 1, 2])
>>> np.exp(B)
array([1. , 2.71828183, 7.3890561 ])
|
Indexing, slicing and iterating
- One-dimensional arrays can be indexed, sliced and iterated over, much like lists and other Python sequences.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| >>> a = np.arange(10)**3
>>> a
array([ 0, 1, 8, 27, 64, 125, 216, 343, 512, 729])
>>> a[2]
8
>>> a[2:5]
array([ 8, 27, 64])
>>> # equivalent to a[0:6:2] = 1000;
>>> # from start to position 6, exclusive, set every 2nd element to 1000
>>> a[:6:2] = 1000
>>> a
array([1000, 1, 1000, 27, 1000, 125, 216, 343, 512, 729])
>>> a[::-1] # reversed a
array([ 729, 512, 343, 216, 125, 1000, 27, 1000, 1, 1000])
>>> for i in a:
... print(i**(1 / 3.))
...
9.999999999999998 # may vary
1.0
9.999999999999998
3.0
9.999999999999998
4.999999999999999
5.999999999999999
6.999999999999999
7.999999999999999
8.999999999999998
|
- Multidimensional arrays can have one index per axis. Thesse indices are given in a tuple separated by commas:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| >>> def f(x, y):
... return 10 * x + y
...
>>> b = np.fromfuction(f, (5, 4), dtype=np.int_)
>>> b
array([[ 0, 1, 2, 3],
[10, 11, 12, 13],
[20, 21, 22, 23],
[30, 31, 32, 33],
[40, 41, 42, 43]])
>>> b[2, 3]
23
>>> b[0:5, 1] # each row in the second column of b
array([ 1, 11, 21, 31, 41])
>>> b[:, 1] # equivalent to the previous example
array([ 1, 11, 21, 31, 41])
>>> b[1:3, :] # each column in the second and third row of b
array([[10, 11, 12, 13],
[20, 21, 22, 23]])
|
… (skip) (more ways to get a slice)
Shape manipulation
Changing the shape of an array
An array has a shape given by the number o felements along each axis:
1
2
3
4
5
6
7
| >>> a = np.floor(10 * rg.random((3, 4)))
>>> a
array([[3., 7., 3., 4.],
[1., 4., 2., 2.],
[7., 2., 4., 9.]])
>>> a.shape
(3, 4)
|
The shape of an array can be changed with various commands. Note that the following three commands all return a modified array, but do not change the original array:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| >>> a.ravel() # returns the flattened array
array([3., 7., 3., 4., 1., 4., 2., 2., 7., 2., 4., 9.])
>>> a.reshape(6, 2) # returns the array with a modified shape
array([[3., 7.],
[3., 4.],
[1., 4.],
[2., 2.],
[7., 2.],
[4., 9.]])
>>> a.T # returns the array, transposed
array([[3., 1., 7.],
[7., 4., 2.],
[3., 2., 4.],
[4., 2., 9.]])
|
By the way: of np.random
init the seed:
1
| >>> np.random.seed(int(hashlib.sha256("Aminiam".encode()).hexdigest(), 16) % (2**32))
|
print:
1
2
3
4
| >>> print(np.random.random((3,3)))
[[0.59908781 0.55341069 0.73192068]
[0.61572755 0.97373193 0.27759232]
[0.53090874 0.57221723 0.63055102]]
|
By the way: of random
1
2
3
4
| >>> import random as rd
>>> rd.seed(10086)
>>> rd.random()
0.043562757723543566
|
View or shallow copy
View() method creates a new array object that looks at the same data.
1
2
3
4
5
6
7
| >>> c = a.view()
>>> c is a
False
>>> c.base is a
True
>>> c.flags.owndata
False
|
Slicing an array returns a view of it.
1
2
| >>> s = a[:, 1:3]
s[:] = 10 # s[:]is a view of `s`. Note the difference between `s=10` and `s[:]=10`
|
Deep copy
The copy() method makes a complete copy f the array and its data.
1
2
3
| >>> d = a.copy()
>>> d is a
False
|
Sometimes copy() should be called after slicing if the original array is not required anymore. For example, suppose a is a huge intermediate result and the final result b only contains a small fraction of a, a deep copy should be made when constructing b with slicing.
Less basic
Broadcasting rules
Broadcasting allows universal functions to deal in a meaningful way with inputs that do not have exactly the same shape.
The first rule of broadcasting is that if all input arrays do not have the same number of dimensions, a “1” will be repeatedly prepended to the shapes of the smaller arrays until all the arrays have the same number of dimensions.
The second rule of broadcasting ensures that arrays with a size of 1 along a particular dimension act as if the had the size of the array with the largest shape along that dimension. The value of the array element is assumed to be the same along that dimension for the “broadcast” array.
After application of the broadcasting rules, the sizes of all arrays must match.
Advanced indexing and index tricks
Indexing with arrays of indices