切片(slice)
切片符号用冒号( : )表示
切片表达式 x[start:stop:step]
如果以上 3 个参数都未指定,那么它们会被分别设置默认值 start=0 、 stop= 维度的大小(size of dimension) 和 step=1 。
一维数组
常用方法
x[:5] # 前五个元素
x[5:] # 索引五之后的元素
x[4:7] # 中间的子数组 ,末尾开区间,不包括索引为7的数
x[::2] # 每隔一个元素
x[1::2] # 每隔一个元素,从索引1开始
步长为负数的神操作
x[::-1] # 所有元素,逆序的
x[5::-2] # 从索引5开始逆序输出,间隔一个数,[5,3,1]
多维数组的切片
多维数组的切片的切片也以同样的方式 :,
在重申一次,切片是开区间
x2[:2, :3] # 两行,三列 ,索引为2,但并不包括2,所以为0,1的2行,列也是同理。
x2[:3, ::2] # 所有行,每隔一列
子数组维度也可以同时被逆序 x2[::-1, ::-1]
通过切片形式索引获取数组的的子数组
一个冒号( : )表示空切片
x2[:, 0] # x2的第一列
print(x2[0, :]) # x2的第一行
print(x2[0]) #可以省略空切片,所以等于x2[0, :]
非副本视图的子数组
关于数组切片有一点很重要也非常有用,那就是数组切片返回的是数组数据的视图,而不是数值数据的副本。这一点也是 NumPy 数组切片和 Python 列表切片的不同之处:在Python 列表中,切片是值的副本。
In[31]: print(x2)
[[12 5 2 4]
[ 7 6 8 8]
[ 1 6 7 7]]
从中抽取一个 2×2 的子数组:
In[32]: x2_sub = x2[:2, :2]
print(x2_sub)
[[12 5]
[ 7 6]]
现在如果修改这个子数组,将会看到原始数组也被修改了!结果如下所示:
In[33]: x2_sub[0, 0] = 99
print(x2_sub)
[[99 5]
[ 7 6]]
In[34]: print(x2)
[[99 5 2 4]
[ 7 6 8 8]
[ 1 6 7 7]]
这种默认的处理方式实际上非常有用:它意味着在处理非常大的数据集时,可以获取或处理这些数据集的片段,而不用复制底层的数据缓存。
尽快数组视图形式给大数据修改提供了方便,但是数据副本还是有很多租用的,如果只是这种数据视图,势必有一些阻碍,先知当然把所有的问题都考虑到了,所以.copy()方法的作用是不可忽视的,他就是复制一个完全独立的子数组。