【numpy】关于numpy的axis=0和1及高维tensor

目录

关于numpy

使用0值表示沿着每一列或行标签\索引值向下执行方法

使用1值表示沿着每一行或者列标签模向执行对应的方法 

那么更高维度呢?还是适用吗?就不适用了!

axis = 0表示对最外层[]里的最大单位块做块与块之间的运算,同时移除最外层[]:

axis= 1表示对第二外层[]里的最大单位块做块与块之间的运算,同时移除第二外层[]:

关于tensor

axis就是数组层级

设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)区分

Python之NumPy(axis=0/1/2...)的透彻理解——通过np.sum(axis=?)实例进行说明

Numpy:对Axis的理解 - ksss的文章 - 知乎

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值