索引和切片

一维数组


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

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

这也意味着,如果不想更改原始数组,我们需要进行显式的复制,从而得到它的副本(.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]])

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

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

多维数组

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

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

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

newshape : int or tuple of ints。整数或者元组

顺便说明下,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 * 列中列

那么:

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之索引和切片的更多相关文章

  1. NumPy学习(索引和切片,合并,分割,copy与deep copy)

    NumPy学习(索引和切片,合并,分割,copy与deep copy) 目录 索引和切片 合并 分割 copy与deep copy 索引和切片 通过索引和切片可以访问以及修改数组元素的值 一维数组 程 ...

  2. Numpy:索引与切片

    numpy基本的索引和切片 import numpy as np arr = np.array([1,2,3,555,666,888,10]) arr array([ 1, 2, 3, 555, 66 ...

  3. Numpy系列(四)- 索引和切片

    Python 中原生的数组就支持使用方括号([])进行索引和切片操作,Numpy 自然不会放过这个强大的特性.  单个元素索引 1-D数组的单元素索引是人们期望的.它的工作原理与其他标准Python序 ...

  4. NumPy 学习 第二篇:索引和切片

    数组索引是指使用中括号 [] 来定位数据元素,不仅可以定位到单个元素,也可以定位到多个元素.索引基于0,并接受从数组末尾开始索引的负索引. 举个例子,正向索引从0开始,从数组开始向末尾依次加1递增:负 ...

  5. numpy数组的索引和切片

    numpy数组的索引和切片 基本切片操作 >>> import numpy as np >>> arr=np.arange(10) >>> arr ...

  6. Numpy入门(二):Numpy数组索引切片和运算

    在Numpy中建立了数组或者矩阵后,需要访问数组里的成员,改变元素,并对数组进行切分和计算. 索引和切片 Numpy数组的访问模式和python中的list相似,在多维的数组中使用, 进行区分: 在p ...

  7. Numpy数组基本操作(数组索引,数组切片以及数组的形状,数组的拼接与分裂)

    一:数组的属性 每个数组都有它的属性,可分为:ndim(数组的维度),shape(数组每个维度的大小),size(数组的总大小),dtype(数组数据的类型) 二:数组索引 和python列表一样,N ...

  8. Numpy学习二:数组的索引与切片

    1.一维数组索引与切片#创建一维数组arr1d = np.arange(10)print(arr1d) 结果:[0 1 2 3 4 5 6 7 8 9] #数组的索引从0开始,通过索引获取第三个元素a ...

  9. 3.3Python数据处理篇之Numpy系列(三)---数组的索引与切片

    目录 (一)数组的索引与切片 1.说明: 2.实例: (二)多维数组的索引与切片 1.说明: 2.实例: 目录: 1.一维数组的索引与切片 2.多维数组的索引与切片 (一)数组的索引与切片 1.说明: ...

随机推荐

  1. RN 导入原有Xcode项目中,引入Pod依赖出现的问题与解决

    RN 导入原有Xcode项目中,引入Pod依赖出现的问题与解决 前言 最近学习React Native技术.将RN引入到原来Xcode项目中有一步:给原来Xcode项目添加所需要的Pod依赖 写好Po ...

  2. Visual Studio Code 使用Chrome Debug 代码

    一.添加插件 Debugger for Chrome,点击安装,安装完成之后,启动 二.配置启动参数 1.按 F5,出现界面如图,选择 Chrome 2.然后会打开配置文件 launch.json 3 ...

  3. 性能调优之MYSQL高并发优化

    性能调优之MYSQL高并发优化   一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之 ...

  4. Android Weekly Notes Issue #251

    Android Weekly Issue #251 April 2nd, 2017 Android Weekly Issue #251. 本期内容: Android O新增的API: View的too ...

  5. 漫谈PHP代码规范

    前言 虽说PHP是世界上最好的语言,但是写出来的PHP代码却往往不是最美观的.究其原因,可能正式因为PHP简单易上手,适合快速迭代的特性,导致了我们沉浸在迅速完成需求迭代的窃喜中,却忘记了规范性.忽略 ...

  6. "!function",自执行函数表达式

    如题为自执行函数表达式.在这种情况下,解析器在解析function关键字的时候,会将相应的代码解析成function表达式,而不是function声明.下面2个括弧()都会立即执行 (function ...

  7. 自定义一个EL函数

    自定义一个EL函数 一般就是一下几个步骤,顺便提供一个工作常用的 案例: 1.编写一个java类,并编写一个静态方法(必需是静态方法),如下所示: public class DateTag { pri ...

  8. javascript核心概念——new

    如果完全没有编程经验的朋友看到这个词会想到什么? 上过幼儿园的都知道new表示 "新的" 的意思. var a = new Date() 按照字面的意思表示什么? 把一个新的dat ...

  9. canvas画图

    这个元素负责在页面中设定一个区域,然后就可以通过JS动态的在这个区域中绘制图形. <canvas>由几组API构成. <canvas>还建议一个名为WebGL的3D上下文 (1 ...

  10. const常量类型

    1.定义:const常量类型表示一个”常值变量“,其值是不能被修改的变量.即一旦变量被声明为const类型,编译器将禁止任何试图修改该变量的操作. 2.声明:const <声明数据类型> ...