Numpy数据分析——花哨索引的简单使用、“广播“规则详解

在对高维数组进行索引时,常会不知从何而起,想提取的部分和实际的效果会出现偏差。

本文将以尽可能容易懂的方式,来揭开Numpy高维数组之间的运算逻辑,并呈现一些简单运用

目录

一、文章用词阐释

1、轴长度和shape

2、广播

二、剖析广播的规则

1、单一标量A(可认为是零维的数组)与一维数组B

2、一维数组与一维数组

情况一:只含一个值的一维数组M和另一个任意长度,元素为任意值的一维数组N:

情况二:两个一维数组数组,长度均不为1,且长度不相等

情况三:两个一维数组,长度一样

3、高维数组(只要两个数组里有一个是二维以上,就满足该条件)

三条基本规则

三、花哨索引——用索引数组来一次性获得多个数组元素

1、用前须知

2、不广播,但与索引数组的形状一致

3、紧急插播,广播与否其实取决于索引数组的来源

4、多维度数组的花哨索引


一、文章用词阐释

此处先解释一下文章中可能会提到的两个名词

1、轴长度和shape

轴长度:下一级的“元素”的个数,如果一个三维数组里有10个二维数组,那么三维的这个维度(由于Numpy中维度和轴是等效的,也可以说成三维的这个轴)的轴长度就是10

ndarray对象的shape属性(反映数组的维度)——以下面两个例子来说明

如果一个数组的shape是(10,10,2),其中参数从左到右的意义是:

在一个三维数组中:有10(左边第一个10)个二维数组,每一个二维数组中有10个一维数组,每个一维数组里有2个元素

我们进一步推广一下,对于一个shape为(A1,A2,…An)的n维数组

他有A1个 (n-1)维数组,每一个(n-1)维数组里有A2个(n-2)维数组……每一个二维数组里有An-1个一维数组,每个一维数组里有An个元素

2、广播

广播可以看作是两个数组进行二元运算所遵循的一套“对应原则”,它是NumPy的一种向量化操作的支撑。

当你在对两个数组进行运算比较,或者你同时引入两个数组参与花式索引时,广播规则在发生作用

二、剖析广播的规则

1、单一标量A(可认为是零维的数组)与一维数组B

A将会被扩展成与B等长的一维数组A''(但实际在内存中并未发生,这样说是为了便于理解)

然后这个想象出来的、被扩展的、里面全是相同值的  A" 将与B进行元素的一一对应

import numpy as np
A=5
B=np.array([4,8,63,2])

B+A  # B中每一个元素与A中相同位置的元素相加 (减乘除)
B>A  # B中每一个元素与A中相同位置的元素比较大小(大于小于等于)(返回一个布尔数组)

2、一维数组与一维数组

情况一:只含一个值的一维数组M和另一个任意长度,元素为任意值的一维数组N:

等同于单一标量A与一个一维数组B

情况二:两个一维数组数组,长度均不为1,且长度不相等

无法进行广播!即使某个数组里的值全相同,你也别指望编译器会把它自动填充

import numpy as np
row=np.array([0,1,2])
col=np.array([2,2])
print(row+col)
#这行不通!当然如果你把col改成[2,3]也行不通
#你将会看到  “could not be broadcast together with shapes (3,) (2,)” 这样的字段

情况三:两个一维数组,长度一样

从左到右挨个对应进行各种操作,你的第一个和我的第一个……

3、高维数组(只要两个数组里有一个是二维以上,就满足该条件)

广播最重要的逻辑在这里展开,核心是扩展成shape相同的两个高维数组

温馨提示:仍然会有无法广播的情况!

三条基本规则

1、如果两个数组的维度数不相同,那么小维度数组的形状将会在最左边补1

阐释:shape中逗号间隔开了几个数字,就是几维,所以数字个数少的就是低维

举例:A的shape(3,2,4) ,B的shape(2,1),A三维,B二维,B是小维度

>>>那么为了让shape在“维度数上一致” ,B的形状将变成(1,2,1),在最左边补1即是这个意思

2、维度数相同了之后,在对应的维度上,如果一个数组在该维度上为1,那它在这个维度上应当扩展成另一个数组在该维度上的值

阐释:对应的维度上:两个数组shape属性中的同一位置的参数

以第一条规则举的例子(我在这里用颜色标记),(3,2,4)与(1,2,1)

在shape中的第一个参数,A是3,B是1,那么B的这个1就会扩展成3

第二个参数,A的2与B的2匹配,无需扩展

第三个参数,A是4,B是1,B的这个1会扩展成4

细心的你一定发现了:shape的值在该维度上为1才能够扩展,不是一的就不动它

那你一定会想:如果在某个维度上A是2,B是3,那广播之后是2,是 3,还是6呢

3、在进行了前两个步骤之后,只要两个数组的shape在某一个维度上,不相同,且都不为一,那这两个数组就无法进行广播!

(2,3)和(2,2)不行;(3,2,1)和(2,2,1)不行————不同且无一,是会引发大异常的

三、花哨索引——用索引数组来一次性获得多个数组元素

1、用前须知

花哨索引(Fancy Indexing)结果的shape,将于索引数组的shape一致

之所以这么说是因为你传入的“筛选标准”——索引数组,有可能也会发生广播。

2、不广播,但与索引数组的形状一致

import numpy as np

x=rand.randint(100,size=10)#随机生成一个长度为10的数组

print(ind=[3,7,4])#一个索引数组

x[ind]#效果相当于x[ind[0]],x[ind[1]],x[ind[2]]
#当然如果抽象化ind,你可以理解成把ind理解成“下标的数组”,会一次性提取完

ind_1=np.array([[3,7],[4,5]])

print(x[ind])#你得到的将会和ind_1长得结构是一致的

#第一行是x中的第4个和第8个,第二行是x中的第5个和第6个

3、紧急插播,广播与否其实取决于索引数组的来源

对一个一维数组,你只能给他一个索引数组,但这个索引数组可以是二维,可以是一维

随便几维(前提是你的索引值需要在下标范围内)

如果这个索引数组是广播而来的——那你自然需要广播(好似废话)

比如两个数组进行二元操作后得到了一个索引操作,二元操作中就极会涉及广播

4、多维度数组的花哨索引

import numpy as np
#In[1]
X=np.arange(12).reshape((3,4))
row=np.array([0,1,2])
col=np.array([2,1,3])
print("X数列的row,col",X[row,col]);

'''注意到,两个一维数组,分别作为索引的两个,是按照广播规则一一对应的'''
#In[2]
print("把row给升维,X[row[:,np.newaxis],col]是\n",X[row[:,np.newaxis],col])

'''
    row会变成[[0],[1],[2]],shape为(3,1),而col的shape为(3,),会广播先统一col和row

    第一步,把col的shape变成(1,3)>>>  col 变为  [[2,1,3]]
    第二步,因为两个shape在这两个维度上都存在1,所以可以参与扩展
    
    row从(3,1)到(3,3)>>> [ [0,0,0]
                           [1,1,1]             
                           [2,2,2] ]沿1这个维度来进行复制

    col从(1,3)到(3,3)>>> [[2,1,3]
                         ,[2,1,3]
                         ,[2,1,3]]

    挨个对应,你的[0,0]位置和我的[0,0]位置,组成一个索引的坐标对

    值得一提的是,扩展其实就是对最原始数组的复制而达成的升维
    再挨个对应
    还需要注意的是shape里的第一个数字i永远是代表n维里有i个(n-1)维数组
    花式索引得到的值反映的是————索引数组广播后的形状!!!
'''

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值