NumPy in Python. Part 3

Translator's Preface


Hello again! We continue our series of articles on numpy mana translation. Enjoy reading.


Comparison operators and value testing


A boolean comparison can be used for element-by-element comparison of arrays of the same length. The return value is an array of Boolean True / False values:

>>> a = np.array([1, 3, 0], float) >>> b = np.array([0, 3, 2], float) >>> a > b array([ True, False, False], dtype=bool) >>> a == b array([False, True, False], dtype=bool) >>> a <= b array([False, True, True], dtype=bool) 

The result of the comparison can be stored in an array:

 >>> c = a > b >>> c array([ True, False, False], dtype=bool) 

Arrays can be compared to a single value:

 >>> a = np.array([1, 3, 0], float) >>> a > 2 array([False, True, False], dtype=bool) 

The operators any and all can be used to determine whether at least one or all of the elements are true, respectively:

 >>> c = np.array([ True, False, False], bool) >>> any(c) True >>> all(c) False 

Combined Boolean expressions can be applied to arrays by the element-element principle using the special functions logical_and, logical_or and logical_not:

 >>> a = np.array([1, 3, 0], float) >>> np.logical_and(a > 0, a < 3) array([ True, False, False], dtype=bool) >>> b = np.array([True, False, True], bool) >>> np.logical_not(b) array([False, True, False], dtype=bool) >>> c = np.array([False, True, False], bool) >>> np.logical_or(b, c) array([ True, True, False], dtype=bool) 

The where function creates a new array of two other arrays of the same length using a boolean filter to select between two elements. Basic syntax: where (boolarray,
truearray, falsearray):

 >>> a = np.array([1, 3, 0], float) >>> np.where(a != 0, 1 / a, a) array([ 1. , 0.33333333, 0. ]) 

With the where function, a "mass comparison" can also be implemented:

 >>> np.where(a > 0, 3, 2) array([3, 3, 2]) 

Some functions make it possible to test values ​​in an array. The nonzero function returns a tuple of indices of nonzero values. The number of elements in a tuple is equal to the number of axes in the array:

 >>> a = np.array([[0, 1], [3, 0]], float) >>> a.nonzero() (array([0, 1]), array([1, 0])) 

You can also check the values ​​for limb and NaN (not a number):

 >>> a = np.array([1, np.NaN, np.Inf], float) >>> a array([ 1., NaN, Inf]) >>> np.isnan(a) array([False, True, False], dtype=bool) >>> np.isfinite(a) array([ True, False, False], dtype=bool) 

Although here we used the numpy constants to add NaN and infinity values, they can be the result of applying standard mathematical operations.

Selecting and manipulating array elements


We have already seen, as with lists, the elements of an array can be obtained using an index access operation. However, unlike lists, arrays also allow you to select items using other arrays. This means that we can use an array to filter specific subsets of elements from other arrays.

Boolean arrays can be used as filtering arrays:

 >>> a = np.array([[6, 4], [5, 9]], float) >>> a >= 6 array([[ True, False], [False, True]], dtype=bool) >>> a[a >= 6] array([ 6., 9.]) 

It is worth noting that when we transfer the Boolean array a> = 6 as an index for an access operation on the index of array a, the returned array will store only True values. We can also write an array for filtering into a variable:

 >>> a = np.array([[6, 4], [5, 9]], float) >>> sel = (a >= 6) >>> a[sel] array([ 6., 9.]) 

More sophisticated filtering can be achieved using boolean expressions:

 >>> a[np.logical_and(a > 5, a < 9)] >>> array([ 6.]) 

In addition to the boolean selection, you can also use integer arrays. In this case, the integer array stores the indices of the elements that will be taken from the array. Consider the following one-dimensional example:

 >>> a = np.array([2, 4, 6, 8], float) >>> b = np.array([0, 0, 1, 3, 2, 1], int) >>> a[b] array([ 2., 2., 4., 8., 6., 4.]) 

In other words, when we use b to get elements from a, we take the 0th, 0th, 1st, 3rd, 2nd, and 1st elements of a in this order. Lists can also be used as filtering arrays:

 >>> a = np.array([2, 4, 6, 8], float) >>> a[[0, 0, 1, 3, 2, 1]] array([ 2., 2., 4., 8., 6., 4.]) 

For multidimensional arrays, we need to transfer several one-dimensional integer arrays to the access operator to the index ( Note of the translator: in our case, the indices are arrays ) for each axis. Then each of the arrays goes through the following sequence: the first element corresponds to the index of the row, which is the first element of the array b, the second element corresponds to the index of the column, which is the first element of the array c, and so on. ( Note of the translator: the first array [2, 2] and the second [1, 4], we have elements with the indices [2, 1] and [2, 4] at the output ) Example:

 >>> a = np.array([[1, 4], [9, 16]], float) >>> b = np.array([0, 0, 1, 1, 0], int) >>> c = np.array([0, 1, 1, 1, 1], int) >>> a[b,c] array([ 1., 4., 16., 16., 4.]) 

The special function take is available for sampling with integer arrays. This works in the same way as using the index operator:

 >>> a = np.array([2, 4, 6, 8], float) >>> b = np.array([0, 0, 1, 3, 2, 1], int) >>> a.take(b) array([ 2., 2., 4., 8., 6., 4.]) 

The take function also provides an axis argument for taking a sub-section of a multidimensional array along an axis. ( Note of the translator: in rows or columns (for two-dimensional arrays) ).

 >>> a = np.array([[0, 1], [2, 3]], float) >>> b = np.array([0, 0, 1], int) >>> a.take(b, axis=0) array([[ 0., 1.], [ 0., 1.], [ 2., 3.]]) >>> a.take(b, axis=1) array([[ 0., 0., 1.], [ 2., 2., 3.]]) 

In contrast to the take function, there is a put function, which will take values ​​from the source array and write them to specific indices in another put-array.

 >>> a = np.array([0, 1, 2, 3, 4, 5], float) >>> b = np.array([9, 8, 7], float) >>> a.put([0, 3], b) >>> a array([ 9., 1., 2., 8., 4., 5.]) 

Note that the value 7 from the source array b was not used, since only 2 indices [0, 3] are indicated. The original array will be repeated if necessary in case of non-matching lengths:

 >>> a = np.array([0, 1, 2, 3, 4, 5], float) >>> a.put([0, 3], 5) >>> a array([ 5., 1., 2., 5., 4., 5.]) 

Vector and matrix mathematics


NumPy provides many functions for working with vectors and matrices. The dot function returns the scalar product of vectors:

 >>> a = np.array([1, 2, 3], float) >>> b = np.array([0, 1, 1], float) >>> np.dot(a, b) 5.0 

The dot function can also multiply matrices:

 >>> a = np.array([[0, 1], [2, 3]], float) >>> b = np.array([2, 3], float) >>> c = np.array([[1, 1], [4, 0]], float) >>> a array([[ 0., 1.], [ 2., 3.]]) >>> np.dot(b, a) array([ 6., 11.]) >>> np.dot(a, b) array([ 3., 13.]) >>> np.dot(a, c) array([[ 4., 0.], [ 14., 2.]]) >>> np.dot(c, a) array([[ 2., 4.], [ 0., 4.]]) 

You can also get the scalar, tensor, and outer product of matrices and vectors. Note that for vectors the inner and inner product coincides.

 >>> a = np.array([1, 4, 0], float) >>> b = np.array([2, 2, 1], float) >>> np.outer(a, b) array([[ 2., 2., 1.], [ 8., 8., 4.], [ 0., 0., 0.]]) >>> np.inner(a, b) 10.0 >>> np.cross(a, b) array([ 4., -1., -6.]) 

NumPy also provides a set of built-in functions and methods for working with linear algebra. This can all be found in the linalg sub-module. These modules can also be operated with degenerate and non-degenerate matrices. The determinant of the matrix is ​​sought as follows:

 >>> a = np.array([[4, 2, 0], [9, 3, 7], [1, 2, 1]], float) >>> a array([[ 4., 2., 0.], [ 9., 3., 7.], [ 1., 2., 1.]]) >>> np.linalg.det(a) -53.999999999999993 

You can also find the eigenvector and eigenvalue of the matrix:

 >>> vals, vecs = np.linalg.eig(a) >>> vals array([ 9. , 2.44948974, -2.44948974]) >>> vecs array([[-0.3538921 , -0.56786837, 0.27843404], [-0.88473024, 0.44024287, -0.89787873], [-0.30333608, 0.69549388, 0.34101066]]) 

A non-degenerate matrix can be found as follows:

 >>> b = np.linalg.inv(a) >>> b array([[ 0.14814815, 0.07407407, -0.25925926], [ 0.2037037 , -0.14814815, 0.51851852], [-0.27777778, 0.11111111, 0.11111111]]) >>> np.dot(a, b) array([[ 1.00000000e+00, 5.55111512e-17, 2.22044605e-16], [ 0.00000000e+00, 1.00000000e+00, 5.55111512e-16], [ 1.11022302e-16, 0.00000000e+00, 1.00000000e+00]]) 

A single decomposition (analogous to the diagonalization of a non-square matrix) can be achieved as follows:

 >>> a = np.array([[1, 3,4], [5, 2, 3]], float) >>> U, s, Vh = np.linalg.svd(a) >>> U array([[-0.6113829 , -0.79133492], [-0.79133492, 0.6113829 ]]) >>> s array([ 7.46791327, 2.86884495]) >>> Vh array([[-0.61169129, -0.45753324, -0.64536587], [ 0.78971838, -0.40129005, -0.46401635], [-0.046676 , -0.79349205, 0.60678804]]) 

We finish the third part. Good luck and see you soon!

Source: https://habr.com/ru/post/413381/


All Articles