How does the axis parameter from NumPy work?

会有一股神秘感。 提交于 2019-11-27 11:21:02

Clearly,

e.shape == (3, 2, 2)

Sum over an axis is a reduction operation so the specified axis disappears. Hence,

e.sum(axis=0).shape == (2, 2)
e.sum(axis=1).shape == (3, 2)
e.sum(axis=2).shape == (3, 2)

Understanding what axis means in numpy:

Consider the 3 dimensional x,y,z coordinate plane:

The axis parameter is a number that communicates to numpy arrays along which dimension you want your aggregate function to operate.

Python numpy/pandas axis mnemonic:

axis=0 means 'along the row', (x in the above image)
axis=1 means 'along the column', (y in the above image)
axis=2 means 'along the depth', (z in the above image)

Image source: https://github.com/sentientmachine/Cheatsheets#python_numpy

Understanding the axis parameter is a necessity if you are to understand numpy vectorization specifically the order of dimensional operations for broadcasting.

Imagine we want to sum across a matrix with three dimensions. A sum could operate along the x, y or z axis, or along all three. By default axis is 0 meaning the outermost dimension, the outermost dimension is the one returned by your_3d_matrix[0]

So if you sum along axis=0, axis=1, or axis=2 you will receive one dimensional sum slices across that dimension.

Example:

a = np.array([[1,2],[3,4]])   #define a simple 2d ndarray

>>> a[0,0]
1
>>> a[0,1]
2
>>> a[1,0]
3
>>> a[1,1]
4


>>> a.sum()                   #axis not specified means first along the col then 
10                            #along the row: (1+3) = 4 and
                              #2+4 = 6 then along the column 4+6 = 10

>>> a.sum(axis=0)             #forcing axis=0 says collapse along the row so:
array([4, 6])                 #1+3 = 4,   2+4 = 6

>>> a.sum(axis=1)             #forcing axis=1 says collapse along the col so:
array([3, 7])                 #1+2 = 3,   3+4 = 7

You can even have axis=2 which is the 2nd dimension down:

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

       [[5, 6],
        [7, 8]]])
>>> b.sum()         #sum along depth, col, then row:
36
>>> b.sum(axis=0)   #sum across the topmost dimension 0, the two groups of 4
array([[ 6,  8],
       [10, 12]])
>>> b.sum(axis=1)   #sum across dimension 1 the lists of two, added.
array([[ 4,  6],
       [12, 14]])
>>> b.sum(axis=2)   #sum across the dimension 2, each individual list, row wise. 
array([[ 3,  7],
       [11, 15]])

The axis orientation depends on the structure it applies to.

The orders of operation of axis collapse starts at outermost, the dimension of yourarray[0] to innermost: yourarray[0][0][0].

Even the developers who coded up this numpy software have trouble creating intuition for the linear algebra governing matrix operations, Youtube videos attempt to explain the axis parameter in depth:

Alexandre Chabot LeClerc NumPy Tutorial that covers the axis parameter: https://youtu.be/gtejJ3RCddE?t=1h55m17s

Data School channel on youtube has an excellent explanation of the axis parameter: https://youtu.be/PtO3t6ynH-8?t=5m1s

To understand the axis intuitively, refer the picture below (source: Physics Dept, Cornell Uni)

The shape of the (boolean) array in the above figure is shape=(8, 3). ndarray.shape will return a tuple where the entries correspond to the length of the particular dimension. In our example, 8 corresponds to length of axis 0 whereas 3 corresponds to length of axis 1.

If someone need this visual description:

There are good answers for visualization however it might help to think purely from analytical perspective.

You can create array of arbitrary dimension with numpy. For example, here's a 5-dimension array:

>>> a = np.random.rand(2, 3, 4, 5, 6)
>>> a.shape
(2, 3, 4, 5, 6)

You can access any element of this array by specifying indices. For example, here's the first element of this array:

>>> a[0, 0, 0, 0, 0]
0.0038908603263844155

Now if you take out one of the dimensions, you get number of elements in that dimension:

>>> a[0, 0, :, 0, 0]
array([0.00389086, 0.27394775, 0.26565889, 0.62125279])

When you apply a function like sum with axis parameter, that dimension gets eliminated and array of dimension less than original gets created. For each cell in new array, the operator will get list of elements and apply the reduction function to get a scaler.

>>> np.sum(a, axis=2).shape
(2, 3, 5, 6)

Now you can check that the first element of this array is sum of above elements:

>>> np.sum(a, axis=2)[0, 0, 0, 0]
1.1647502999560164

>>> a[0, 0, :, 0, 0].sum()
1.1647502999560164

The axis=None has special meaning to flatten out the array and apply function on all numbers.

Now you can think about more complex cases where axis is not just number but a tuple:

>>> np.sum(a, axis=(2,3)).shape
(2, 3, 6)

Note that we use same technique to figure out how this reduction was done:

>>> np.sum(a, axis=(2,3))[0,0,0]
7.889432081931909

>>> a[0, 0, :, :, 0].sum()
7.88943208193191

You can also use same reasoning for adding dimension in array instead of reducing dimension:

>>> x = np.random.rand(3, 4)
>>> y = np.random.rand(3, 4)

# New dimension is created on specified axis
>>> np.stack([x, y], axis=2).shape
(3, 4, 2)
>>> np.stack([x, y], axis=0).shape
(2, 3, 4)

# To retrieve item i in stack set i in that axis 

Hope this gives you generic and full understanding of this important parameter.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!