Detailed axis / axes in Numpy

First, in Numpy, the dimensions are expanded by axes, and the number of axes is called rank. The rank here is not the rank in linear algebra, it still refers to the number of dimensions :

The number of axes (dimensions) of the array. In the Python world, the number of dimensions is referred to as rank.

 In the concept of mathematics or physics, dimensions are considered to be the minimum number of coordinates needed to represent a point in space, but in Numpy, dimensions refer to axes. In other words, the concepts of axes, dimensions, and rank are interlinked.

The following example, for example, we define three points in 3-D space, expressed in the form of array:

>>> import numpy as np
>>> a = np.array([[1,2,3],[2,3,4],[3,4,9]])
>>> a
array([[1, 2, 3],
       [2, 3, 4],
       [3, 4, 9]])

According to previous understanding, we may think that this array is three-dimensional, but in fact, in Numpy, the dimensions of this array, that is, the value of rank is equal to 2:

>>> np.ndim(a)
2

Because it has only two axes, but the length of both axes is 3:

>>> np.shape(a)
(3, 3)

Meanwhile, this matrix in linear algebra rank in the (rank) is still 3 (to be distinguished herein):

>>> np.linalg.matrix_rank(a)
3

In other words, in Numpy, any vector is regarded as a one-dimensional array with different lengths.


Let's continue to talk about axis / axes, we still define a 3-D array first:

>>> b = np.array([[[1,2,3,4],[1,3,4,5]],[[2,4,7,5],[8,4,3,5]],[[2,5,7,3],[1,5,3,7]]])
>>> b
array([[[1, 2, 3, 4],
        [1, 3, 4, 5]],

       [[2, 4, 7, 5],
        [8, 4, 3, 5]],

       [[2, 5, 7, 3],
        [1, 5, 3, 7]]])
>>> b.shape
(3, 2, 4)

We have defined an array of shape (3, 2, 4). This shape (represented by tuple) can be understood as the size on each axis (that is, the length occupied) and the three Meaning: axis = 0 corresponds to the element on the axis length = 3, axis = 1 corresponds to the element on the axis length = 2, axis = 2 corresponds to the element on the axis length = 4, that is, when we select a certain element in the array The maximum index range that may be used for each element , for example:

>>> b[1]
array([[2, 4, 7, 5],
       [8, 4, 3, 5]])
>>> b[1,:,:]             # Equivalent value
array([[2, 4, 7, 5],
       [8, 4, 3, 5]])

Here b [1] and b [1,:,:] mean that the first element is selected on the axis = 0 axis, and all elements on axis = 1 and axis = 2 are selected at the same time. We can temporarily think of multiple axes as multiple layers , of course, we can also think of it as a tree structure. Although it is not accurate to say so, for convenience of imagination, we can temporarily understand this:

axis = 0 indicates the first layer: the effect seen in the code is that b counts the first layer [] from outside to inside, and the corresponding element (length = 3) is all the elements separated by commas in the first layer [] ( Note: Do not pay attention to the comma in the second layer and above []), it is obvious that the number of elements in this layer is 3; Similarly, axis = 1 means the second layer: the first layer is separated by a comma In any [], all elements separated by commas (length = 2); axis = 2 is the same, which means the elements in the last layer (length = 4). It's still a bit confusing to say so, I rearranged the array just now:

In the style of writing c / c ++ code with apes like this, black represents the first layer, you can see there are three elements, red represents the second layer, and there are two elements under the same premise of the first layer , Blue represents the third layer, there are 4 elements under the premise that the first layer and the second layer are the same. This corresponds to the result of b.shape = (3, 2, 4).

At this time, what should we index if we want to locate element 8? It can be seen that 8 is in the second element of the first layer, at the same time in the second element of the second layer and the first element of the third layer, that is to say: 8 is on the axis = 0 axis The second position of axis, axis = the second position on the axis, and the first position of axis = 2 jointly retrieve the elements. Write the code:

>>> b[1,1,0]

8

噔 噔 噔 ~ Just sauce. At the same time , we can also find that the array has several dimensions, and we can use several integers to index its elements .

Looking further, for the array b, the position corresponding to the last element is the maximum index that can be used (starting from 0):

>>> b[2,1,3]
7

If it is bigger on any axis, IndexError will appear:

>>> b[2,1,4]

Traceback (most recent call last):
  File "<pyshell#38>", line 1, in <module>
    b[2,1,4]
IndexError: index 4 is out of bounds for axis 2 with size 4

The reason for setting different axes is that we can process different dimensions of data. For example, now we have collected data from four classmates scoring the love of three fruits, apple, durian and watermelon (total score is 10). Each classmate has three characteristics:

>>> item = np.array([[1,4,8],[2,3,5],[2,5,1],[1,10,7]])
>>> item
array([[1, 4, 8],
       [2, 3, 5],
       [2, 5, 1],
       [1, 10, 7]])

Each row contains three characteristics of the same person. If we want to see which student likes to eat fruit the most, we can use:

>>> item.sum(axis = 1)
array([13, 10,  8, 18])

It can be roughly seen that classmate 4 likes to eat fruit the most.

If we want to see which fruit is the most popular, we can use:

>>> item.sum(axis = 0)
array([ 6, 22, 21])

It can be seen that durian is the most popular ~~~ yeah ~~~ cough, this is the meaning of axis existence--in order to conveniently process the data from different angles.


Next, we will calculate the higher-dimensional array. We will use some functions that provide the parameter of axis to further explain the concept of the axis:

It is still a summation: ndarray.sum (axis = None, dtype = None, out = None, keepdims = False), equivalent to numpy.sum (a, axis = None, dtype = None, out = None, keepdims = False ):

>>> b.sum()
94
>>> b.sum(axis = 0)
array([[ 5, 11, 17, 12],
       [10, 12, 10, 17]])
>>> b.sum(axis = 1)
array([[ 2,  5,  7,  9],
       [10,  8, 10, 10],
       [ 3, 10, 10, 10]])
>>> b.sum(axis = 2)
array([[10, 13],
       [18, 20],
       [17, 16]])

When axis is not set, sum returns the sum of all elements; when axis is specified, it means that all elements in a certain axis are summed correspondingly, and the layer is collapsed at the same time, because this process is a reduction operation . For example, when seeking b.sum (axis = 1), we still return to this figure:

axis = 1, intuitively, it means that we need to pay attention to the elements between the red layers, and sequentially sum the elements between the different red boxes at the same position on the two axes of axis = 0 and axis = 2 (good mouth) ), That is, the connected elements in the following figure correspond to the summation:

Can be obtained (non-standard writing): 

array([
        [ 2,  5,  7,  9],
        [10,  8, 10, 10],
        [ 3, 10, 10, 10]
      ])

That is to say, assuming that the array after summation is b_sum, we have:

b_sum[0, 0] = b[0, 0, 0]+b[0, 1, 0]; b_sum[0, 1] = b[0, 0, 1]+b[0, 1, 1]; b_sum[0, 2] = b[0, 0, 2]+b[0, 1, 2]; b_sum[0, 3] = b[0, 0, 3]+b[0, 1, 3];

b_sum[1, 0] = b[1, 0, 0]+b[1, 1, 0]; b_sum[1, 1] = b[1, 0, 1]+b[1, 1, 1]; b_sum[1, 2] = b[1, 0, 2]+b[1, 1, 2]; b_sum[1, 3] = b[1, 0, 3]+b[1, 1, 3];

b_sum[2, 0] = b[2, 0, 0]+b[2, 1, 0]; b_sum[2, 1] = b[2, 0, 1]+b[2, 1, 1]; b_sum[2, 2] = b[2, 0, 2]+b[2, 1, 2]; b_sum[2, 3] = b[2, 0, 3]+b[2, 1, 3];

That is, when axis = 0 and axis = 2 are the same, the result obtained by summing all the elements on axis = 1.

At the same time, after summing the elements on this axis, this axis disappears, we can check the shape after summing:

>>> b.sum(axis = 1).shape
(3, 4)

It can be seen that the sum of the elements on axis = 1 collapses from the original (3, 2, 4) to (3, 4), and the other axes can be verified by themselves.


Next look at the sorting function: ndarray.sort (axis = -1, kind = 'quicksort', order = None), you can also use numpy.sort (a, axis = -1, kind = 'quicksort', order = None ), But the former will change b and the latter will not change b:

>>> np.sort(b)
array([[[1, 2, 3, 4],
        [1, 3, 4, 5]],

       [[2, 4, 5, 7],
        [3, 4, 5, 8]],

       [[2, 3, 5, 7],
        [1, 3, 5, 7]]])
>>> np.sort(b, axis = 0)
array([[[1, 2, 3, 3],
        [1, 3, 3, 5]],

       [[2, 4, 7, 4],
        [1, 4, 3, 5]],

       [[2, 5, 7, 5],
        [8, 5, 4, 7]]])
>>> np.sort(b, axis = 1)
array([[[1, 2, 3, 4],
        [1, 3, 4, 5]],

       [[2, 4, 3, 5],
        [8, 4, 7, 5]],

       [[1, 5, 3, 3],
        [2, 5, 7, 7]]])

In the first case, the default axis value of sort is -1. For our case, it is equivalent to sorting the elements on the axis = 2 axis (that is, the penultimate axis).

Let's take one of the cases as an example. For axis = 0, first of all, we need to pay attention to the corresponding elements between the black boxes:

I only marked out the corresponding relationship between the first group of elements and the last group of elements in the process of sorting on the axis axis = 0, and the other groups of elements are the same.

It can also be expressed from the perspective of index:

Sort b [0, 0, 0], b [1, 0, 0], b [2, 0, 0], and rearrange the results from small to large;

Sort b [0, 0, 1], b [1, 0, 1], b [2, 0, 1], and rearrange the results from small to large;

Sort b [0, 0, 2], b [1, 0, 2], b [2, 0, 2], and rearrange the results from small to large;

Sort b [0, 0, 3], b [1, 0, 3], b [2, 0, 3], and rearrange the results from small to large;

Sort b [0, 1, 0], b [1, 1, 0], b [2, 1, 0], and rearrange the results from small to large;

The rest is the same ...

Well, just give these two examples first. Other functions with parameter axis can also be analyzed from these two perspectives.

130 original articles published · Like 30 · Visits 40,000+

Guess you like

Origin blog.csdn.net/W_H_M_2018/article/details/105536728