目录
axis = 0表示对最外层[]里的最大单位块做块与块之间的运算,同时移除最外层[]:
axis= 1表示对第二外层[]里的最大单位块做块与块之间的运算,同时移除第二外层[]:
设axis=i,则numpy沿着第i个下标变化的方向进行操作
结论:沿着哪一维操作,最后这一维度消失。
关于numpy
python中的axis究竟是如何定义的呢?他们究竟代表是DataFrame的行还是列?考虑以下代码:
import pandas as pd
df = pd.DataFrame([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], \
columns=["col1", "col2", "col3", "col4"])
print(df)
col1 col2 col3 col4
0 1 1 1 1
1 2 2 2 2
2 3 3 3 3
df.mean(axis=1),将得到按行计算的均值
print(df.mean(axis=1))
0 1.0
1 2.0
2 3.0
df.drop((name, axis=1),我们实际上删掉了一列,而不是一行
print(df.drop("col4", axis=1))
col1 col2 col3
0 1 1 1
1 2 2 2
2 3 3 3
but!
print(df.drop("col4", axis=0))
报错
"""
print(df.drop("col4", axis=0))
File "D:\appp\Python\lib\site-packages\pandas\core\frame.py", line 3997, in drop
errors=errors,
File "D:\appp\Python\lib\site-packages\pandas\core\generic.py", line 3936, in drop
obj = obj._drop_axis(labels, axis, level=level, errors=errors)
File "D:\appp\Python\lib\site-packages\pandas\core\generic.py", line 3970, in _drop_axis
new_axis = axis.drop(labels, errors=errors)
File "D:\appp\Python\lib\site-packages\pandas\core\indexes\base.py", line 5018, in drop
raise KeyError(f"{labels[mask]} not found in axis")
KeyError: "['col4'] not found in axis"
"""
Can someone help me understand what is meant by an "axis" in pandas/numpy/scipy?
有人能帮我理解一下,在pandas、numpy、scipy三都当中axis参数的真实含义吗?
投票最高的答案揭示了问题的本质:
其实问题理解axis有问题,df.mean其实是在每一行上取所有列的均值,而不是保留每一列的均值。也许简单的来记就是axis=0代表往跨行(down),而axis=1代表跨列(across),作为方法动作的副词(译者注)
换句话说:
使用0值表示沿着每一列或行标签\索引值向下执行方法
使用1值表示沿着每一行或者列标签模向执行对应的方法
下图代表在DataFrame当中axis为0和1时分别代表的含义:
axis参数作用方向图示
另外,记住,Pandas保持了Numpy对关键字axis的用法,用法在Numpy库的词汇表当中有过解释:
轴用来为超过一维的数组定义的属性,二维数据拥有两个轴:第0轴沿着行的垂直往下,第1轴沿着列的方向水平延伸。
所以问题当中第一个列子 df.mean(axis=1)代表沿着列水平方向计算均值,而第二个列子df.drop(name, axis=1) 代表将name对应的列标签(们)沿着水平的方向依次删掉。
那么更高维度呢?还是适用吗?就不适用了!
第一个块是4,6而不是3,7。axis=1就不是按行了
np.array([[[1,2],[3,4]],[[11,12],[13,14]]])
a.sum(axis = 1)
>>>array([[ 4, 6], [24, 26]])
二维情况还是符合0按列,1按行的。
b = np.array([[1,2],[3,4]])
print(b.sum(axis=0)) # [4 6]
print(b.sum(axis=1)) # [3 7]
print(np.mean(b,axis=0)) # [2. 3.]
numpy中axis取值的说明
首先对numpy中axis取值进行说明:一维数组时axis=0,二维数组时axis=0,1,维数越高,则axis可取的值越大,数组n维时,axis=0,1,…,n。为了方便下面的理解,我们这样看待:在numpy中数组都有着[]标记,则axis=0对应着最外层的[],axis=1对应第二外层的[],以此类推,axis=n对应第n外层的[]。
下面开始从axis=0,axis=1这两个例子开始,深入透彻的理解numpy中axis的用法。
axis = 0表示对最外层[]里的最大单位块做块与块之间的运算,同时移除最外层[]:
a= np.array([1,2,3])
a.sum(axis = 0)
>>>6
因为只有一层[],所以直接对这一层里的最大单位快1,2,3做运算;
做完加法后本应是[6],但是移除最外层[]后,[]不存在了,所以返回的是6。
a= np.array([[1,2],[3,4]])
a.sum(axis = 0)
>>>array([4, 6])
有两层[],最外层[]里的最大单位块分别为[1,2],[3,4],对这两个单位块做块与块之间的运算,[1,2]+[3,4] = [4, 6];
做完加法后本应是[[4, 6]],但是移除最外层[]后,原来的两层[]变成一层[],所以返回结果为 [4, 6]。
np.array([[[1,2],[3,4]],[[11,12],[13,14]]])
a.sum(axis = 0)
>>>array([[12, 14], [16, 18]])
有三层[],最外层[]里的最大单位块分别为[[1,2],[3,4]],[[11,12],[13,14]],对这两个单位块做块与块之间的运算,[[1,2],[3,4]] + [[11,12],[13,14]] = [[12, 14], [16, 18]];
做完加法后本应是[[[12, 14], [16, 18]]],但是移除最外层[]后,原来的三层[]变成两层[],所以返回结果为[[12, 14], [16, 18]];
axis= 1表示对第二外层[]里的最大单位块做块与块之间的运算,同时移除第二外层[]:
a= np.array([1,2,3])
a.sum(axis = 1)
>>>ValueError: 'axis' entry is out of bounds
因为只有一层[],axis取值只有一个,为0.
a= np.array([[1,2],[3,4]])
a.sum(axis = 1)
>>>array([3, 7])
有两层[],第二外层[]里的最大单位块有两组(因为有两个第二外层[]),第一组是1,2,第二组是3,4,分别对这两个单位块做块与块之间的运算,第一组结果为1+2=3,第二组结果为3+4=7;
做完加法后本应是[[3],[7]],但是**移除第二外层[]**后,原来的两层[]变成一层[],所以返回结果为[3, 7]。
np.array([[[1,2],[3,4]],[[11,12],[13,14]]])
a.sum(axis = 1)
>>>array([[ 4, 6], [24, 26]])
有三层[],第二外层[]里的最大单位块有两组(因为有两个第二外层[]),第一组是[1,2],[3,4],第二组是[11,12],[13,14],分别对这两个单位块做块与块之间的运算,第一组结果为[1,2]+[3,4] = [ 4, 6],第二组结果为[11,12]+[13,14] = [24, 26]
做完加法后本应是[[[ 4, 6]], [[24, 26]]],但是**移除第二外层[]**后,原来的三层[]变成两层[],所以返回结果为[[ 4, 6], [24, 26]]
axis = 3,4,5也如此分析。
关于tensor
其实和高维的numpy是一样的分析思路,见第二部分,那个就是很直观的感受分析。这个画图的更加有逻辑一些(个人感受)。
- axis就是数组层级
- 设axis=i,则numpy沿着第i个下标变化的方向进行操作
axis就是数组层级
要想理解axis,首先我们先要弄清楚“Numpy中数组的维数”和"线性代数中矩阵的维数"这两个概念以及它们之间的关系。在数学或者物理的概念中,dimensions被认为是在空间中表示一个点所需要的最少坐标个数,但是在Numpy中,dimensions指代的是数组的维数。比如下面这个例子:
>>> 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]])
这个array的维数只有2,即axis轴有两个,分别是axis=0和axis=1。如下图所示,该二维数组的第0维(axis=0)有三个元素(左图),即axis=0轴的长度length为3;第1维(axis=1)也有三个元素(右图),即axis=1轴的长度length为3。正是因为axis=0、axis=1的长度都为3,矩阵横着竖着都有3个数,所以该矩阵在线性代数是3维的(rank秩为3)。
因此,axis就是数组层级。
当axis=0,该轴上的元素有3个(数组的size为3)
a[0]
、a[1]
、a[2]
当axis=1,该轴上的元素有3个(数组的size为3)
a[0][0]
、a[0][1]
、a[0][2]
(或者a[1][0]
、a[1][1]
、a[1][2]
)
(或者a[2][0]
、a[2][1]
、a[2][2]
)
再比如下面shape为(3,2,4)的array:
>>> 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)
这个shape(用tuple表示)可以理解为在每个轴(axis)上的size,也即占有的长度(length)。为了更进一步理解,我们可以暂时把多个axis想象成多层layers。axis=0表示第一层(下图黑色框框),该层数组的size为3,对应轴上的元素length = 3;axis=1表示第二层(下图红色框框),该层数组的size为2,对应轴上的元素length = 2;axis=2表示第三层(下图蓝色框框),对应轴上的元素length = 4。
设axis=i,则numpy沿着第i个下标变化的方向进行操作
- 1.二维数组示例:
比如np.sum(a, axis=1)
,结合下面的数组, a[0][0]
=1、a[0][1]
=2、a[0][2]
=3 ,下标会发生变化的方向是数组的第一维。
我们往下标会变化的方向,把元素相加后即可得到最终结果:
[
[6],
[9],
[16]
]
- 2.三维数组示例:
再举个例子,比如下边这个np.shape(a)=(3,2,4)
的3维数组,该数组第0维的长度为3(黑色框框),再深入一层,第1维的长度为2(红色框框),再深入一层,第2维的长度为4(蓝色框框)。
如果我们要计算np.sum(a, axis=1)
,在第一个黑色框框中,
下标的变化方向如下所示:
所以,我们要把上下两个红色框框相加起来
按照同样的逻辑处理第二个和第三个黑色的框框,可以得出最终结果:
所以,依然是我们前边总结的那一句话,设axis=i,则Numpy沿着第i个下标变化的方向进行操作。
- 3.四维数组示例:
比如下面这个巨复杂的4维数组,
>>> data = np.random.randint(0, 5, [4,3,2,3])
>>> data
array([[[[4, 1, 0],
[4, 3, 0]],
[[1, 2, 4],
[2, 2, 3]],
[[4, 3, 3],
[4, 2, 3]]],
[[[4, 0, 1],
[1, 1, 1]],
[[0, 1, 0],
[0, 4, 1]],
[[1, 3, 0],
[0, 3, 0]]],
[[[3, 3, 4],
[0, 1, 0]],
[[1, 2, 3],
[4, 0, 4]],
[[1, 4, 1],
[1, 3, 2]]],
[[[0, 1, 1],
[2, 4, 3]],
[[4, 1, 4],
[1, 4, 1]],
[[0, 1, 0],
[2, 4, 3]]]])
当axis=0时,numpy沿着第0维的方向进行求和,也就是第一个元素值=a0000+a1000+a2000+a3000=11,第二个元素=a0001+a1001+a2001+a3001=5,同理可得最后的结果如下:
>>> data.sum(axis=0)
array([[[11, 5, 6],
[ 7, 9, 4]],
[[ 6, 6, 11],
[ 7, 10, 9]],
[[ 6, 11, 4],
[ 7, 12, 8]]])
因为数组是4*3*2*3,沿着第0维操作,axis=0,最后结果为3*2*3。记得不要看array的最外面的【】!
当axis=3时,numpy沿着第3维的方向进行求和,也就是第一个元素值=a0000+a0001+a0002=5,第二个元素=a0010+a0011+a0012=7,同理可得最后的结果如下:
>>> data.sum(axis=3)
array([[[ 5, 7],
[ 7, 7],
[10, 9]],
[[ 5, 3],
[ 1, 5],
[ 4, 3]],
[[10, 1],
[ 6, 8],
[ 6, 6]],
[[ 2, 9],
[ 9, 6],
[ 1, 9]]])
因为数组是4*3*2*3,沿着第3维操作,axis=3,最后结果为4*3*2。记得不要看array的最外面的【】! 直接算数组大小
axis的应用
例如现在我们收集了四个同学对苹果、榴莲、西瓜这三种水果的喜爱程度进行打分的数据(总分为10),每个同学都有三个特征:
>>> 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]])
每一行包含了同一个人的三个特征,如果我们想看看哪个同学最喜欢吃水果,那就可以用:
>>> item.sum(axis = 1)
array([13, 10, 8, 18])
可以大概看出来同学4最喜欢吃水果。
如果我们想看看哪种水果最受欢迎,那就可以用:
>>> item.sum(axis = 0)
array([ 6, 22, 21])
可以看出基本是榴莲最受欢迎。
参考:
Python之NumPy(axis=0 与axis=1)区分