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实现网站的模拟登录
Jan 04 Python
浅谈flask截获所有访问及before/after_request修饰器
Jan 18 Python
python3.x 将byte转成字符串的方法
Jul 17 Python
使用pip发布Python程序的方法步骤
Oct 11 Python
详解Django的model查询操作与查询性能优化
Oct 16 Python
详解【python】str与json类型转换
Apr 29 Python
关于Python 的简单栅格图像边界提取方法
Jul 05 Python
深入了解如何基于Python读写Kafka
Dec 31 Python
Tensorflow读取并输出已保存模型的权重数值方式
Jan 04 Python
Python字符串格式化常用手段及注意事项
Jun 17 Python
Python爬虫回测股票的实例讲解
Jan 22 Python
Python之qq自动发消息的示例代码
Feb 18 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
ubuntu 编译安装php 5.3.3+memcache的方法
2010/08/05 PHP
PHP5中GD库生成图形验证码(有汉字)
2013/07/28 PHP
php 伪静态之IIS篇
2014/06/02 PHP
检测codeigniter脚本消耗内存情况的方法
2015/03/21 PHP
删除PHP数组中的重复元素的实现代码
2017/04/10 PHP
Laravel5.5+ 使用API Resources快速输出自定义JSON方法详解
2020/04/06 PHP
JavaScript格式化数字的函数代码
2010/11/30 Javascript
js 一个关于图片onload加载的事
2013/11/10 Javascript
jQuery简单实现禁用右键菜单
2015/03/10 Javascript
jQuery实现定位滚动条位置
2016/08/05 Javascript
JavaScript性能优化之函数节流(throttle)与函数去抖(debounce)
2016/08/11 Javascript
微信小程序开发教程之增加mixin扩展
2017/08/09 Javascript
Vue-Quill-Editor富文本编辑器的使用教程
2018/09/21 Javascript
js简单遍历获取对象中的属性值的方法示例
2019/06/19 Javascript
layui使用表格渲染获取行数据的例子
2019/09/13 Javascript
Python 异常处理实例详解
2014/03/12 Python
Python批量重命名同一文件夹下文件的方法
2015/05/25 Python
利用Python学习RabbitMQ消息队列
2015/11/30 Python
Python3实现的画图及加载图片动画效果示例
2018/01/19 Python
Python根据文件名批量转移图片的方法
2018/10/21 Python
在python下使用tensorflow判断是否存在文件夹的实例
2019/06/10 Python
Django后端接收嵌套Json数据及解析详解
2019/07/17 Python
推荐8款常用的Python GUI图形界面开发框架
2020/02/23 Python
python+requests接口压力测试500次,查看响应时间的实例
2020/04/30 Python
python 3.8.3 安装配置图文教程
2020/05/21 Python
python属于解释型语言么
2020/06/15 Python
Python grpc超时机制代码示例
2020/09/14 Python
python 两种方法删除空文件夹
2020/09/29 Python
英国玛莎百货美国官网:Marks & Spencer美国
2018/11/06 全球购物
init进程的作用
2015/08/20 面试题
关于抽烟的检讨书
2014/02/25 职场文书
党小组考察意见
2015/06/02 职场文书
商业计划书之服装
2019/09/09 职场文书
简单谈谈Python面向对象的相关知识
2021/06/28 Python
浅谈Redis中的RDB快照
2021/06/29 Redis
微信小程序中使用vant框架的具体步骤
2022/02/18 Javascript