numpy中索引和切片详解


Posted in Python onDecember 15, 2017

索引和切片

一维数组

一维数组很简单,基本和列表一致。

它们的区别在于数组切片是原始数组视图(这就意味着,如果做任何修改,原始都会跟着更改)。

这也意味着,如果不想更改原始数组,我们需要进行显式的复制,从而得到它的副本(.copy())。

import numpy as np #导入numpy
arr = np.arange(10) #类似于list的range()
arr
Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
arr[4] #索引(注意是从0开始的)
Out[4]: 4
arr[3:6] #切片
Out[6]: array([3, 4, 5])
arr_old = arr.copy() #先复制一个副本
arr_old
Out[8]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
arr[3:6] = 33
arr #可以发现将标量赋值给一个切片时,该值可以传播到整个选区
Out[10]: array([ 0, 1, 2, 33, 33, 33, 6, 7, 8, 9])
arr_old
Out[11]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

二维数组

二维数组中,各索引位置上的元素不再是标量,而是一维数组(好像很难理解哈)。

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

arr1[0]
Out[13]: array([1, 2, 3])

arr1[1,2]
Out[14]: 6

好像很难理解,是吧。

那这样看:

array([[1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]])

想到了什么?咱们当做一个平面直角坐标系。

numpy中索引和切片详解

相当于arr1[x,y],x相当于行数,y相当于列数(必须声明,图中x和y标反了,但不影响理解)。

多维数组

先说明下reshape()更改形状:

np.reshape(a,newshape,order='C')

a:array_like以一个数组为参数。

newshape:intortupleofints。整数或者元组

顺便说明下,np.reshape()不更改原数组形状(会生成一个副本)。

arr1 = np.arange(12)
arr2 = arr1.reshape(2,2,3) #将arr1变为2×2×3数组

arr2
Out[9]: 
array([[[ 0, 1, 2],
    [ 3, 4, 5]],

    [[ 6, 7, 8],
    [ 9, 10, 11]]])

其实多维数组就相当于:

row * col * 列中列

numpy中索引和切片详解

那么:

arr2[0]
Out[10]: 
array([[0, 1, 2],
    [3, 4, 5]])
arr2[1]
Out[11]: 
array([[ 6, 7, 8],
    [ 9, 10, 11]])
arr2[0,1]
Out[12]: array([3, 4, 5])
arr2[0] = 23 #赋值
arr2
Out[15]: 
array([[[23, 23, 23],
    [23, 23, 23]],
    [[ 6, 7, 8],
    [ 9, 10, 11]]])

切片索引

那么这样也就很容易的就可以理解下面这种索引了。

切片索引把每一行每一列当做一个列表就可以很容易的理解。

返回的都是数组。

再复杂一点:

我们想要获得下面这个数组第一行的第2,3个数值。

arr1 = np.arange(36)#创建一个一维数组。

arr2 = arr1.reshape(6,6) #更改数组形状。
Out[20]: 
array([[ 0, 1, 2, 3, 4, 5],
    [ 6, 7, 8, 9, 10, 11],
    [12, 13, 14, 15, 16, 17],
    [18, 19, 20, 21, 22, 23],
    [24, 25, 26, 27, 28, 29],
    [30, 31, 32, 33, 34, 35]])

为了得到第2,3个数,我们可以:

arr2[0,2:4]
Out[29]: array([2, 3])

可以发现ndarray的切片其实与列表的切片是差不太多的。

我们还可以这样:

arr2[1] #取得第2行
Out[37]: array([ 6, 7, 8, 9, 10, 11])
arr2[:,3] #取得第3列, 只有:代表选取整列(也就是整个轴)
Out[38]: array([ 3, 9, 15, 21, 27, 33])
arr2[1:4,2:4] # 取得一个二维数组
Out[40]: 
array([[ 8, 9],
    [14, 15],
    [20, 21]])
arr2[::2,::2] #设置步长为2
Out[41]: 
array([[ 0, 2, 4],
    [12, 14, 16],
    [24, 26, 28]])
arr3 = arr2.reshape(4,3,3)
arr3[2:,:1] = 22 #对切片表达式赋值
arr3
Out[25]: 
array([[ 0, 1, 2, 3, 4, 5],
    [ 6, 7, 8, 9, 10, 11],
    [22, 13, 14, 15, 16, 17],
    [22, 19, 20, 21, 22, 23],
    [22, 25, 26, 27, 28, 29],

布尔型索引

arr3 = (np.arange(36)).reshape(6,6)#生成6*6的数组
arr3
Out[35]: 
array([[ 0, 1, 2, 3, 4, 5],
    [ 6, 7, 8, 9, 10, 11],
    [12, 13, 14, 15, 16, 17],
    [18, 19, 20, 21, 22, 23],
    [24, 25, 26, 27, 28, 29],
    [30, 31, 32, 33, 34, 35]])
x = np.array([0, 1, 2, 1, 4, 5])
x == 1#通过比较运算得到一个布尔数组
Out[42]: array([False, True, False, True, False, False], dtype=bool)
arr3[x == 1] #布尔索引
Out[43]: 
array([[ 6, 7, 8, 9, 10, 11],
    [18, 19, 20, 21, 22, 23]])

从结果上看,布尔索引取出了布尔值为True的行。
布尔型数组的长度和索引的数组的行数(轴长度)必须一致。
布尔型数组可与切片,整数(整数序列)一起使用。

arr3[x == 1,2:]#切片
Out[44]: 
array([[ 8, 9, 10, 11],
    [20, 21, 22, 23]])

arr3[x == 1,-3:]#切片
Out[47]: 
array([[ 9, 10, 11],
    [21, 22, 23]])

arr3[x == 1,3]#整数
Out[48]: array([ 9, 21])

!= 不等于符号。
~ 负号可以对条件进行否定。logical_not()函数也可以。

x != 1
Out[49]: array([ True, False, True, False, True, True], dtype=bool)
arr3[~(x == 1)] #实际类似于取反
Out[51]: 
array([[ 0, 1, 2, 3, 4, 5],
    [12, 13, 14, 15, 16, 17],
    [24, 25, 26, 27, 28, 29],
    [30, 31, 32, 33, 34, 35]])
arr3[np.logical_not(x == 1)] #作用于 ~ 相同
Out[53]: 
array([[ 0, 1, 2, 3, 4, 5],
    [12, 13, 14, 15, 16, 17],
    [24, 25, 26, 27, 28, 29],
    [30, 31, 32, 33, 34, 35]])

组合多个条件,使用布尔运算符&(和),|(或)

(x == 1 ) & (x == 4)#和
Out[67]: array([False, False, False, False, False, False], dtype=bool)
(x==1)|(x==4)#或
Out[68]: array([False, True, False, True, True, False], dtype=bool)
arr3[(x==1)|(x==4)]#布尔索引
Out[71]: 
array([[ 6, 7, 8, 9, 10, 11],
    [18, 19, 20, 21, 22, 23],
    [24, 25, 26, 27, 28, 29]])

通过以上的代码实验,我们也可以发现,布尔索引不更改原数组,创建的都是原数组的副本。

那这个东西能做什么呢?其他索引能做的,他基本也都可以。

比如有这样一个数组:

arr5 = np.random.randn(4,4)#randn返回一个服从标准正态分布的数组。

arr5
Out[77]: 
array([[-0.64670829, 1.53428435, 0.20585387, 0.42680995],
    [-0.63504514, 0.54542881, -0.82163028, -0.89835051],
    [-0.66770299, 0.22617913, 0.16358189, -0.75074314],
    [-0.25439447, -0.96135628, -0.10552532, -1.06962358]])

我们要将arr5大于0的数值变为10:

arr5[arr5 > 0] = 10

arr5
Out[80]: 
array([[ -0.64670829, 10.    , 10.    , 10.    ],
    [ -0.63504514, 10.    , -0.82163028, -0.89835051],
    [ -0.66770299, 10.    , 10.    , -0.75074314],

当然,布尔索引也可以结合上面的运算符来进行操作。

花式索引

花式索引(Fancy indexing),指的是利用整数数组进行索引。

第一次看到这个解释,我是一脸懵的。

试验后,我才理解。

arr6 = np.empty((8,4))# 创建新数组,只分配内存空间,不填充值

for i in range(8):#给每一行赋值
  arr6[i] = i
  arr6
Out[5]: 
array([[ 0., 0., 0., 0.],
    [ 1., 1., 1., 1.],
    [ 2., 2., 2., 2.],
    [ 3., 3., 3., 3.],
    [ 4., 4., 4., 4.],
    [ 5., 5., 5., 5.],
    [ 6., 6., 6., 6.],
    [ 7., 7., 7., 7.]])
arr6[[2,6,1,7]] #花式索引
Out[14]: 
array([[ 2., 2., 2., 2.],
    [ 6., 6., 6., 6.],
    [ 1., 1., 1., 1.],
    [ 7., 7., 7., 7.]])

我们可以看到花式索引的结果,以一个特定的顺序排列。
而这个顺序,就是我们所传入的整数列表或者ndarray。
这也为我们以特定的顺序来选取数组子集,提供了思路。

arr6[2]
Out[15]: array([ 2., 2., 2., 2.])
arr6[6]
Out[17]: array([ 6., 6., 6., 6.])
arr6[1]
Out[18]: array([ 1., 1., 1., 1.])

可以看到,花式索引的结果与普通索引是一致的。只不过,花式索引简化了索引过程,而且还实现了按一定的顺序排列。

还可以使用负数(其实类似于列表)进行索引。

arr6[[-2,-6,-1]]
Out[21]: 
array([[ 6., 6., 6., 6.],
    [ 2., 2., 2., 2.],
    [ 7., 7., 7., 7.]])

一次传入多个索引数组,会返回一个一维数组,其中的元素对应各个索引元组。

有点懵。

arr7 = np.arange(35).reshape(5,7)#生成一个5*7的数组

arr7
Out[24]: 
array([[ 0, 1, 2, 3, 4, 5, 6],
    [ 7, 8, 9, 10, 11, 12, 13],
    [14, 15, 16, 17, 18, 19, 20],
    [21, 22, 23, 24, 25, 26, 27],
    [28, 29, 30, 31, 32, 33, 34]])

arr7[[1,3,2,4],[2,0,6,5]]
Out[27]: array([ 9, 21, 20, 33])

经过对比可以发现,返回的一维数组中的元素,分别对应(1,2)、(3,0)....

这一样一下子就清晰了,我们传入来两个索引数组,相当于传入了一组平面坐标,从而进行了定位。

此处,照我这样理解的话,那么一个N维数组,我传入N个索引数组的话,是不是相当于我传入了一个N维坐标。

我试验了下三维,是这样的,但是以后的不知道了。谁知道求告诉。

ar = np.arange(27).reshape(3,3,3)

ar
Out[31]: 
array([[[ 0, 1, 2],
    [ 3, 4, 5],
    [ 6, 7, 8]],

    [[ 9, 10, 11],
    [12, 13, 14],
    [15, 16, 17]],

    [[18, 19, 20],
    [21, 22, 23],
    [24, 25, 26]]])

ar[[1,2],[0,1],[2,2]]
Out[32]: array([11, 23])

那么应该如何得到一个矩形区域呢。可以这样做:

arr7[[1,3,2,4]][:,[2,0,6,5]]
Out[33]: 
array([[ 9, 7, 13, 12],
    [23, 21, 27, 26],
    [16, 14, 20, 19],
    [30, 28, 34, 33]])

必须明白,arr7[2][3]等价于arr7[2,3]

那么上面这种得到矩形区域的方法,就相当于行与列去了交集。

此外还可用np.ix_函数,它的作用与上面的方法类似,只不过是将两个一维的数组转换为了一个可以选择矩形区域的索引器。

arr7[np.ix_([1,3,2,4],[2,0,6,5])]
Out[34]: 
array([[ 9, 7, 13, 12],
    [23, 21, 27, 26],
    [16, 14, 20, 19],
    [30, 28, 34, 33]])

通过,这些试验,还可发现,花式索引将数据复制到了一个新的数组中。

总结

以上就是本文关于numpy中索引和切片详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:

如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
python发送邮件示例(支持中文邮件标题)
Feb 16 Python
python实现多线程采集的2个代码例子
Jul 07 Python
在类Unix系统上开始Python3编程入门
Aug 20 Python
Python切片操作实例分析
Mar 16 Python
python更改已存在excel文件的方法
May 03 Python
python切片及sys.argv[]用法详解
May 25 Python
python实现决策树分类
Aug 30 Python
django 类视图的使用方法详解
Jul 24 Python
PYTHON如何读取和写入EXCEL里面的数据
Oct 28 Python
在pycharm中为项目导入anacodna环境的操作方法
Feb 12 Python
使用keras和tensorflow保存为可部署的pb格式
May 25 Python
Python使用random模块实现掷骰子游戏的示例代码
Apr 29 Python
Python实现简单网页图片抓取完整代码实例
Dec 15 #Python
利用numpy实现一、二维数组的拼接简单代码示例
Dec 15 #Python
神经网络python源码分享
Dec 15 #Python
神经网络理论基础及Python实现详解
Dec 15 #Python
浅谈机器学习需要的了解的十大算法
Dec 15 #Python
python实现协同过滤推荐算法完整代码示例
Dec 15 #Python
python3大文件解压和基本操作
Dec 15 #Python
You might like
PHP+ajax 无刷新删除数据
2010/02/20 PHP
PHP微信开发之二维码生成类
2015/06/26 PHP
PHP图像处理 imagestring添加图片水印与文字水印操作示例
2020/02/06 PHP
用tip解决Ext列宽度不够的问题
2008/12/13 Javascript
理解Javascript_13_执行模型详解
2010/10/20 Javascript
ajax java 实现自动完成功能
2012/12/19 Javascript
javascript中常用编程知识
2013/04/08 Javascript
javascript使用for循环批量注册的事件不能正确获取索引值的解决方法
2014/12/20 Javascript
jQuery插件slides实现无缝轮播图特效
2015/04/17 Javascript
jquery中添加属性和删除属性
2015/06/03 Javascript
easyui Droppable组件实现放置特效
2015/08/19 Javascript
基于JS2Image实现圣诞树代码
2015/12/24 Javascript
JS 实现导航菜单中的二级下拉菜单的几种方式
2016/10/31 Javascript
微信小程序 引用其他js文件实现代码
2017/02/22 Javascript
JavaScript正则替换HTML标签功能示例
2017/03/02 Javascript
node实现基于token的身份验证
2018/04/09 Javascript
如何使用less实现随机下雪动画详解
2019/01/02 Javascript
微信小程序实现点击空白隐藏的方法示例
2019/08/13 Javascript
element-ui中el-upload多文件一次性上传的实现
2020/12/02 Javascript
[08:04]TI4西雅图DOTA2前线报道 海涛探访各路人马
2014/07/09 DOTA
[50:15]VP vs Mineski 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
[01:10:03]OG vs EG 2018国际邀请赛淘汰赛BO3 第三场 8.23
2018/08/24 DOTA
用Python代码来解图片迷宫的方法整理
2015/04/02 Python
python对html代码进行escape编码的方法
2015/05/04 Python
python魔法方法-属性访问控制详解
2016/07/25 Python
python 读取修改pcap包的例子
2019/07/23 Python
python getopt模块使用实例解析
2019/12/18 Python
如何一键升级Python所有包
2020/11/05 Python
使用CSS3来绘制一个月食图案
2015/07/18 HTML / CSS
浅谈基于HTML5的在线视频播放方案
2016/02/18 HTML / CSS
德国奢侈品网上商城:Mytheresa
2016/08/24 全球购物
精灵市场:Pixie Market
2019/06/18 全球购物
美丽的珠宝配饰:SmallThings
2019/09/04 全球购物
澳大利亚礼品篮网站:Macarthur Baskets
2019/10/14 全球购物
大专生毕业的自我评价
2014/02/06 职场文书
超市创业计划书
2014/09/15 职场文书