Note for Numpy

Very Basics

The basics

NumPy’s array class is called ndarray.

Properties:

  1. ndarray.ndim: dimansions/axes of the arrary.

  2. ndarray.shape: $(x, y, z, t, \cdots) : tuple?$

  3. ndarray.size: the total number of elements of the array.

  4. ndarray.dtype: ?

  5. 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

  • using array():
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:

1
A * B

matrix product:

1
A @ B

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

comments powered by Disqus
冷暖世情,比比如畫。
Built with Hugo