# Python Basics - Numpy Numerical Calculation

NumPy provides a multidimensional array object called ndarray whose elements have a fixed size. That is, NumPy array elements are homogeneous and can only store objects of the same data type. It can use vectorized operation to process the entire array, which has high operation efficiency.

# array creation

## Create an ndarray array through the array() function

The array() function can take a Python list, tuple, array, or other sequence type as a parameter to create an ndarray array.

```import numpy as np
a1 = np.array([1, 2, 3, 4, 5, 6]) #one-dimensional list
print("a1=",a1)

a2 = np.array([[1, 2, 3], [4, 5, 6]]) #two-dimensional list
print("a2=",a2)

a3 = np.array('abcdf') #string
print("a3=",a3)

a4 = np.array((1, 2, 3)) #tuple
print("a4=",a4)

a5 = np.array({'zhang':12, 'dd':45}) #dictionary
print("a5=",a5)
```
```## output ##
a1= [1 2 3 4 5 6]
a2= [[1 2 3]
[4 5 6]]
a3= abcdf
a4= [1 2 3]
a5= {'zhang': 12, 'dd': 45}
```

## create special array

NumPy provides functions for creating special arrays

```import numpy as np
n1 = np.empty((2, 3))
print("empty()Create a number without a specific value, the size of the matrix is ​​in parentheses:\n",n1)

n2 = np.zeros((3, 5))
print("zeros()Create an array of all 0s, with the matrix shape in parentheses:\n",n2)

n3 = np.ones((4, 2))
print("ones()Create an array of all 1s, with the matrix shape in parentheses:\n",n3)

n4 = np.eye(3)
print("eye()Create a square N×N The identity matrix, in parentheses is N value of:\n",n4)

n5 = np.ones_like(n1)
print("ones_like()create and n1 An array of all 1s with the same shape:\n",n5)
```
```## output ##
empty()Create a number without a specific value, the size of the matrix is ​​in parentheses:
[[0. 0. 0.]
[0. 0. 0.]]
zeros()Create an array of all 0s, with the matrix shape in parentheses:
[[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0.]]
ones()Create an array of all 1s, with the matrix shape in parentheses:
[[1. 1.]
[1. 1.]
[1. 1.]
[1. 1.]]
eye()Create a square N×N The identity matrix, in parentheses is N value of:
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
ones_like()create and n1 An array of all 1s with the same shape:
[[1. 1. 1.]
[1. 1. 1.]]
```

## Create an array from a range of values

There are three NumPy functions that create arrays from numerical ranges: arange(),linspace(),logspace();

numpy.arange(start, stop, step, dtype) #The range is left closed and right open, step——step size: default value "1", dtype——return ndarray data type, if not provided, use the type of input data;

np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None) #Generate num samples of equal step size, if the endpoint is True, the value of stop is included, otherwise it is not included; If retstep is True, the spacing will be displayed, otherwise it will not be displayed;

np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None) #Generate num samples with equal step size, if the endpoint is True, the value of stop is included, otherwise it is not included; base——the base of log arithm, dtype——the data type of ndarray.

```import numpy as np
c1 = np.arange(10)
c2 = np.linspace(1, 10, 10) #Arithmetic value
c3 = np.logspace(10, 100, 10) #Proportional value
print("c1=",c1)
print("c2=",c2)
print("c3=",c3)
```
```## output ##
c1= [0 1 2 3 4 5 6 7 8 9]
c2= [ 1.  2.  3.  4.  5.  6.  7.  8.  9. 10.]
c3= [1.e+010 1.e+020 1.e+030 1.e+040 1.e+050 1.e+060 1.e+070 1.e+080 1.e+090
1.e+100]
```

## Create NumPy arrays using the asarray() function

The function asarray() converts Python lists, tuples, etc. to NumPy arrays:

numpy.asarray(a, dtype=None, order=None)

```import numpy as np
d1 = [1, 2, 3, 4, 5, 6]
d2 = np.asarray(d1)
print(d2,d2.dtype)
```
```## output ##
[1 2 3 4 5 6] int32
```

## array of random numbers

In the numpy.random module, a variety of random generation functions are provided:

The rand() function, the values ​​in the array obey the uniform distribution between [0,1);

The uniform() function, uniform(low=0.0, high=1.0, size=None) returns an array whose range is evenly distributed in [low,high);

The randn() function returns an array of a specified shape, and the values ​​in the array follow a standard normal distribution (mean is 0 and variance is 1);

The normal() function, numpy.random.normal(loc=0.0, scale=1.0, size=None) generates an array with a shape specified by size, and the values ​​in the array obey the normal distribution of μ=loc, σ=scale;

The randint() function, numpy.random.randint(low, high=None, size=None, dtype='1') generates an array of discrete uniform sampling in the interval [low,high);

numpy.random.random(size=None), the random() function generates a uniformly sampled array between [0,1).

```import numpy as np
a1 = np.random.rand(2, 4) #matrix shape
print("rand()obey[0,1)A uniform distribution between:\n",a1)
print("")

a2 = np.random.uniform(size=(2, 4)) #Matrix shape, [low,high) is the default value [0,1)
b2 = np.random.uniform(3, 5, (2, 4)) #low=3, high=5
print("uniform()return[low,high)Uniformly distributed arrays in:\n",a2)
print(b2)
print("")

a3 = np.random.randn(2, 4) #Returns an array of the specified shape, the values ​​in the array follow the standard normal distribution
print("randn()Returns an array of the specified shape, the values ​​in the array follow the standard normal distribution:\n",a3)
print("")

a4 = np.random.normal(size=(2, 4))
print("normal()The values ​​in the function-generated array obeyμ=loc,σ=scale Normal distribution of:\n",a4)
print("")

a5 = np.random.randint(1, 10, size=(2, 4))
print("randint()The function generates an interval[low,high)Discrete uniformly sampled array in;\n",a5)
print("")

a6 = np.random.random((2, 4))
print("random()function generation[0,1)Arrays sampled uniformly between:\n",a6)
```
```## output ##
rand()obey[0,1)A uniform distribution between:
[[0.50117497 0.09453935 0.24949911 0.35242339]
[0.27614506 0.45828183 0.59054133 0.7599126 ]]

uniform()return[low,high)Uniformly distributed arrays in:
[[0.83404081 0.29614946 0.87971516 0.68255478]
[0.76991185 0.75489118 0.24766135 0.40941723]]
[[4.95719423 4.47697204 3.69370563 4.73220347]
[3.72110036 3.42003985 3.35648397 3.97719674]]

randn()Returns an array of the specified shape, the values ​​in the array follow the standard normal distribution:
[[ 0.56189735  0.03944787  1.10676961 -0.9235279 ]
[ 1.16715689  0.98365254 -1.48988996  1.40805524]]

normal()The values ​​in the function-generated array obeyμ=loc,σ=scale Normal distribution of:
[[-0.65418483  0.25075608 -0.60689788 -0.21853615]
[ 1.22485674 -0.82383098  0.68833713 -1.03313177]]

randint()The function generates an interval[low,high)Discrete uniformly sampled array in;
[[4 1 2 5]
[7 6 9 6]]

random()function generation[0,1)Arrays sampled uniformly between:
[[0.59022693 0.06508505 0.24775246 0.30724648]
[0.32689472 0.54365446 0.13251454 0.89979262]]
```

## Array Object Properties

```import numpy as np
a = np.array([np.arange(3), np.linspace(3, 5, 3)])
print(np.arange(5).T) #Transpose of 1D array to itself (no change)
print("a=",a)
print("Rank, the number of data axes:",a.ndim,"shape:", a.shape,"Total number of elements:", a.size, "Element type:",a.dtype,"Size in bytes of each element:", a.itemsize, "byte size×Number of data:",a.nbytes)
print("Array transpose:\n",a.T)
for item in a.flat: #The flat iterator traverses the array
print(item, end=",")
```
```## output ##
[0 1 2 3 4]
a= [[0. 1. 2.]
[3. 4. 5.]]
Rank, the number of data axes: 2 shape: (2, 3) Total number of elements: 6 Element types: float64 Size in bytes of each element: 8 bytes in size×Number of data: 48
Array transpose:
[[0. 3.]
[1. 4.]
[2. 5.]]
0.0,1.0,2.0,3.0,4.0,5.0,
```

## array data type

1. dtype specifies the data type
2, astype conversion data type

```import numpy as np
a = np.array([[1.1, 2.2],[3.3, 3.4]],dtype=np.float)
b = a.astype(np.int)
print('a=',a)
print('b=',b)
c = np.arange(5, dtype=np.int8)
print('c=',c)
print('c.dtype=',c.dtype)
print('After data type conversion dtype=',c.astype(np.float).dtype)
print('After data type conversion c=',c.astype(np.float))
print('c The data type of the c.dtype=',c.dtype)
```
```## output ##
a= [[1.1 2.2]
[3.3 3.4]]
b= [[1 2]
[3 3]]
c= [0 1 2 3 4]
c.dtype= int8
After data type conversion dtype= float64
After data type conversion c= [0. 1. 2. 3. 4.]
c The data type of the c.dtype= int8
```

# Array indexing and slicing

## array index

1D array index

```import numpy as np
a = np.linspace(-10, 10, 11)
print(a)
a[0], a[1], a[2] = 100, 200, 300
print(a)
```
```## output ##
[-10.  -8.  -6.  -4.  -2.   0.   2.   4.   6.   8.  10.]
[100. 200. 300.  -4.  -2.   0.   2.   4.   6.   8.  10.]
```

2D array index

```import numpy as np
a = np.arange(12).reshape(3, 4)
print('a=',a)
print('a[0]=',a[0], 'a[2]=',a[2])
print('a[0][0]=',a[0][0], 'a[0,0]=',a[0,0], 'a[1][2]=',a[1][2], 'a[1,2]=',a[1,2])
a[0] = 10
print("a[0]after edited a",a)
a[2,0] = 1000
print("a[2,0]after edited a",a)
```
```## output ##
a= [[ 0  1  2  3]
[ 4  5  6  7]
[ 8  9 10 11]]
a[0]= [0 1 2 3] a[2]= [ 8  9 10 11]
a[0][0]= 0 a[0,0]= 0 a[1][2]= 6 a[1,2]= 6
a[0]after edited a [[10 10 10 10]
[ 4  5  6  7]
[ 8  9 10 11]]
a[2,0]after edited a [[  10   10   10   10]
[   4    5    6    7]
[1000    9   10   11]]
```

## array slice

The format of one-dimensional array slice is [starting_index, ending_index, step], step is the step size, the principle of left closed and right open, the default value is [0,1);

The multidimensional array is sliced ​​along the axis, the default is the 0 axis.

```import numpy as np
#1D array slice
a = np.arange(12)
print('a=',a)
print('a[1:3]=',a[1:3], 'a[9:]=',a[9:])
print('a[1:7:2]=',a[1:7:2])
print('a[:]=', a[:])
```
```## output ##
a= [ 0  1  2  3  4  5  6  7  8  9 10 11]
a[1:3]= [1 2] a[9:]= [ 9 10 11]
a[1:7:2]= [1 3 5]
a[:]= [ 0  1  2  3  4  5  6  7  8  9 10 11]
```
```import numpy as np
#2D array slice
a = np.arange(12).reshape(3, 4)
print('a=',a)
print('a[0:2][1:3]=',a[0:2][1:3], 'a[2:][:2]=',a[2:][1:2]) #They are all indexes on the 0 axis, take the intersection
print('a[0:2]=',a[0:2])
```
```## output ##
a= [[ 0  1  2  3]
[ 4  5  6  7]
[ 8  9 10 11]]
a[0:2][1:3]= [[4 5 6 7]] a[2:][:2]= []
a[0:2]= [[0 1 2 3]
[4 5 6 7]]
```

## boolean index

Note: The length of the boolean array must match the length of the axis corresponding to the destination array

```import numpy as np
from numpy.random import randn
name = np.array(['open','king','plum','Zhao','money']) #row index
data = randn(5,3)
print(data)
print('The line corresponding to the money:',data[name=='money'])
```
```## output ##
[[ 2.37684956 -2.13037039 -1.63255503]
[ 1.05606501  1.64442386 -0.48824817]
[ 0.38975109  1.51344443  0.71365647]
[ 0.46663813 -0.62115848 -0.03084856]
[-0.49633786  0.34521226  0.86970657]]
The line corresponding to the money: [[-0.49633786  0.34521226  0.86970657]]
```
```import numpy as np
a = np.arange(12).reshape(3, 4)
print(a)
print('a>5', a>5)
print('a[a>5]', a[a>5])
```
```## output ##
[[ 0  1  2  3]
[ 4  5  6  7]
[ 8  9 10 11]]
a>5 [[False False False False]
[False False  True  True]
[ True  True  True  True]]
a[a>5] [ 6  7  8  9 10 11]
```

## fancy index

Indexing through a list or array of integers can also be done using the np.ix_() function.

```import numpy as np
a = np.arange(16).reshape(4, 4)
print(a)
print('Fancy index 1:\n', a[[0, 2, 3]][[0, 2]]) #"rows" index the first array and then the second array
print('Fancy index 2:\n', a[[0, 2, 3]][:, [0, 2]]) #"row, column"
print('ix=\n', np.ix_([0, 2, 3], [0, 2]))
print('Fancy index 3:\n', a[np.ix_([0, 2, 3], [0, 2])])
```
```## output ##
[[ 0  1  2  3]
[ 4  5  6  7]
[ 8  9 10 11]
[12 13 14 15]]
Fancy index 1:
[[ 0  1  2  3]
[12 13 14 15]]
Fancy index 2:
[[ 0  2]
[ 8 10]
[12 14]]
ix=
(array([[0],
[2],
[3]]), array([[0, 2]]))
Fancy index 3:
[[ 0  2]
[ 8 10]
[12 14]]
```

# Linear Algebra

## array multiplication

1. dot() function: Calculate the matrix product of two arrays;
2. vdot() function: Calculate the dot product of two vectors.

```import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6], [7, 8]])
c = np.dot(a, b)
d = np.vdot(a, b)
print(a)
print(b)
print('dot=', c)
print('vdot=', d)
```
```## output ##
[[1 2]
[3 4]]
[[5 6]
[7 8]]
dot= [[19 22]
[43 50]]
vdot= 70
```

## matrix determinant

The numpy.linalg.det() function computes the determinant of the input matrix.

```import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.linalg.det(a)
print(b)
```
```## output ##
-2.0000000000000004
```

## inverse matrix

The numpy.linalg.inv() function computes the multiplicative inverse of a matrix.
Note: If the matrix is ​​singular or non-square, using the inv() function to invert the matrix will result in an error.

```import numpy as np
a = np.array([[1, 2], [3, 4]])
b = np.linalg.inv(a)
print(a)
print(b)
print(np.dot(a, b))
```
```## output ##
[[1 2]
[3 4]]
[[-2.   1. ]
[ 1.5 -0.5]]
[[1.00000000e+00 1.11022302e-16]
[0.00000000e+00 1.00000000e+00]]
```

## system of linear equations

The solve() function in numpy.linalg can solve linear equations;
Linear equation system 𝐴𝑥=𝑏 , where A is a matrix, b is a one-dimensional or two-dimensional array, and x is an unknown quantity.
Let the known linear equations be: 𝑥+𝑦+𝑧=6; 2𝑦+5𝑧=−4; 2𝑥+5𝑦=27

```import numpy as np
A = np.mat("1 1 1; 0 2 5; 2 5 -1");
b = np.array([6, -4, 27])
x = np.linalg.solve(A, b)
print('Equation solution:',x)
print(x.ndim) #dimension
print(np.dot(A, x)) #verify
```
```## output ##
Equation solution: [ 5.  3. -2.]
1
[[ 6. -4. 27.]]
```

## Eigenvalues ​​and Eigenvectors

Use the eigvals() function and eig() function provided by the numpy.linalg package;
Where eigvals() returns the eigenvector of the matrix, and the eig() function returns a tuple whose elements are the eigenvalues ​​and eigenvectors.

```import numpy as np
A = np.mat("1 -1; 2 4")
print(A)
e = np.linalg.eigvals(A)
print('evigvals Eigenvalues:', e)
e, v = np.linalg.eig(A)
print("eig Eigenvalues:", e)
print("eig Feature vector:", v)
d = v * np.diag(e) * np.linalg.inv(v) #original matrix
print('original matrix:', d)
```
```## output ##
[[ 1 -1]
[ 2  4]]
evigvals Eigenvalues: [2. 3.]
eig Eigenvalues: [2. 3.]
eig Feature vector: [[-0.70710678  0.4472136 ]
[ 0.70710678 -0.89442719]]
original matrix: [[ 1. -1.]
[ 2.  4.]]
```

# array access

Numpy stores the array through the np.savetxt() function, reads the stored array file through the np.loadtxt() function, and loads it into an array.

```import numpy as np
a = np.arange(12).reshape(3, 4)
np.savetxt('1.txt', a)
```## output ##