numpy的索引、切片与迭代

副本与视图

个人理解 副本很好理解,视图呢,也可把它看成原样本

  • numpy.ndarray.copy() 函数创建一个副本。 对副本数据进行修改,不会影响到原始数据,它们物理内存不在同一位置。
import numpy as np
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
y = x
y[0] = -1
print(x)
print(y)
[-1  2  3  4  5  6  7  8]
[-1  2  3  4  5  6  7  8]
  • 以上例子说明直接赋值后,改变赋值后的变量,原数据也随之修改
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
y = x.copy()
y[0] = -1
print(x)
print(y)
[1 2 3 4 5 6 7 8]
[-1  2  3  4  5  6  7  8]
  • 数组切片操作返回的对象只是原数组的视图,通俗的说就是通过切片修改数据后,源数据也会随之改变
x = np.array([[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]])
y = x
y[::2, :3:2] = -1
print(x)
print(y)
[[-1 12 -1 14 15]
 [16 17 18 19 20]
 [-1 22 -1 24 25]
 [26 27 28 29 30]
 [-1 32 -1 34 35]]
[[-1 12 -1 14 15]
 [16 17 18 19 20]
 [-1 22 -1 24 25]
 [26 27 28 29 30]
 [-1 32 -1 34 35]]
x = np.array([[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]])
y = x.copy()
y[::2, :3:2] = -1
print(x)
print(y)
[[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]]
[[-1 12 -1 14 15]
 [16 17 18 19 20]
 [-1 22 -1 24 25]
 [26 27 28 29 30]
 [-1 32 -1 34 35]]

索引与切片

整数索引

#获取单个元素
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print(x[2])
3
x = np.array([[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]])
print(x[2])
#当只有一个数字时,他代表 行,索引从0开始
[21 22 23 24 25]
#获取第三行二个元素
#方法一
print(x[2][1])
22
#方法二
print(x[2, 1])
22

切片索引

注意

  • python 列表进行切片操作得到的数组是原数组的副本
  • 而对 Numpy 数据进行切片操作得到的数组则是指向相同缓冲区的视图。
  • 切片形式( start:stop:step )
  • 为了更好地理解切片语法,还应该了解不明确指明起始和结束位置的情况。如省去第一个数字,numpy 会认为第一个数字是0;如省去第二个数字,numpy 则会认为第二个数字是数组的最大索引值;如省去最后一个数字,它将会被理解为1,也就是抽取所有元素而不再考虑间隔。
#一维
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print(x[0:2])
[1 2]
print(x[0:5:2])
[1 3 5]
#巧用负数索引
print(x[::-1])
[8 7 6 5 4 3 2 1]
#二维
x = np.array([[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]])
print(x[0:2])
#取前两行
[[11 12 13 14 15]
 [16 17 18 19 20]]
print(x[0:2:2])
[[11 12 13 14 15]]
print(x[:-2])#左闭右开
[[11 12 13 14 15]
 [16 17 18 19 20]
 [21 22 23 24 25]]
print(x[2, :])
#取第三行所有元素
[21 22 23 24 25]
#取所有行第三列元素
print(x[:, 2])
[13 18 23 28 33]
#取第一行第二到三个元素
print(x[0, 1:4])
#当我们知道怎么去取二维数组的值时,也就会了怎么修改某个元素的值
[12 13 14]
  • 总结:对于二维切片(针对二维数组),其中格式为(切片一, 切片二),其中切片一是对二维数组的行进行操作,切片二是对二维数组的列进行操作,若切片一或者切片二为具体数字,则是指定行数或者列数

dots 索引

NumPy 允许使用…表示足够多的冒号来构建完整的索引列表。

比如,如果 x 是 5 维数组:

  • x[1,2,…] 等于 x[1,2,:,:,:]
  • x[…,3] 等于 x[:,:,:,:,3]
  • x[4,…,5,:] 等于 x[4,:,:,5,:]
    -* 通俗来说就是用省略号来代替冒号,numpy会自动计算缺失的冒号个数
x = np.random.randint(1, 100, [2, 2, 3])
print(x)
[[[56 20 94]
  [75 11 33]]

 [[41 92 59]
  [60 66 63]]]
#第一个维度上取第一行其余另两个维度取所有
print(x[1, ...])
[[41 92 59]
 [60 66 63]]
print(x[...,2])
[[94 33]
 [59 63]]

整数数组索引

方括号内传入多个索引值,可以同时选择多个元素。

x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
r = [0, 1, 2]
#代表取第前三个元素
print(x[r])
[1 2 3]
r = [0, 1, -1]
print(x[r])
[1 2 8]
x = np.array([[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]])
r = [0, 1, 2]
#此时代表取前三行,列不做要求
print(x[r])
[[11 12 13 14 15]
 [16 17 18 19 20]
 [21 22 23 24 25]]
r = [0, 1, -1]
print(x[r])
[[11 12 13 14 15]
 [16 17 18 19 20]
 [31 32 33 34 35]]
r = [0, 1, 2]
c = [2, 3, 4]
print(x[r, c])
[13 19 25]
  • 注意, 此处r和c的维度必须相同,不然会报错,而且r与c中的每个数字相对应,上例中是取第一行第三个元素、第二行第四个元素、第三行第五个元素
r = [0, 1, 2]
c = [1, 2, 3, 4]
print(x[r, c])
---------------------------------------------------------------------------

IndexError                                Traceback (most recent call last)

<ipython-input-31-0eb63a79f178> in <module>
      1 r = [0, 1, 2]
      2 c = [1, 2, 3, 4]
----> 3 print(x[r, c])


IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (4,) 
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
r = np.array([[0, 1], [3, 4]])
print(x[r])
[[1 2]
 [4 5]]
x = np.array([[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]])
r = np.array([[0, 1], [3, 4]])
#都取行数
print(x[r])
[[[11 12 13 14 15]
  [16 17 18 19 20]]

 [[26 27 28 29 30]
  [31 32 33 34 35]]]
r = np.array([[0, 0], [4, 4]])
c = np.array([[0, 4], [0, 4]])
print(x[r, c])
#为什么是这样的结果呢?我们要这样看,竖着看,就是(0, 0)(0, 4)(4, 0)(4, 4)第一个数字代表行,第二个数字代表列
[[11 15]
 [31 35]]
print(x[r])
[[[11 12 13 14 15]
  [11 12 13 14 15]]

 [[31 32 33 34 35]
  [31 32 33 34 35]]]
#可以借助切片:与整数数组组合
x = np.array([[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]])
y = x[0:3, [1, 2, 2]]
#在前三行中取值,列数取第二列、第三列、第三列
print(y)
[[12 13 13]
 [17 18 18]
 [22 23 23]]
  • numpy. take(a, indices, axis=None, out=None, mode=‘raise’) Take elements from an array along an axis.
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
r = [0, 1, 2]
print(np.take(x, r))
[1 2 3]
r = [1, 2, -1]
print(np.take(x, r))
[2 3 8]
x = np.array([[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]])
r = [0, 1, 2]
print(np.take(x, r, axis=0))
#axis=0表明对行进行操作
[[11 12 13 14 15]
 [16 17 18 19 20]
 [21 22 23 24 25]]
r = [0, 1, -1]
print(np.take(x, r, axis=0))
[[11 12 13 14 15]
 [16 17 18 19 20]
 [31 32 33 34 35]]
r = [0, 1, 2]
c = [2, 3, 4]
y = np.take(x, [r, c])#r和c否是默认对第一行进行操作的
print(y)
[[11 12 13]
 [13 14 15]]
r = [0, 1, 2]
c = [2, 3, 4]
y = np.take(x, [r, c], axis = 0)#r和c否是默认对第一行进行操作的
print(y)
[[[11 12 13 14 15]
  [16 17 18 19 20]
  [21 22 23 24 25]]

 [[21 22 23 24 25]
  [26 27 28 29 30]
  [31 32 33 34 35]]]
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
r = [0, 1, 2]
c = [2, 3, 4]
print(np.take(x, [r, c]))
[[1 2 3]
 [3 4 5]]
  • 注意:使用切片索引到numpy数组时,生成的数组视图将始终是原始数组的子数组, 但是整数数组索引,不是其子数组,是形成新的数组。
#切片索引
a=np.array([[1,2],[3,4],[5,6]])
b = a[0:1, 0:1]#使用切片索引
print(b)
[[1]]
b[0, 0] = 2
print(b)
[[2]]
print(a[0, 0] == b)
[[ True]]
#a与b共享“相对应”的存储位置
a[0, 0]
2
#整数数组索引
a=np.array([[1,2],[3,4],[5,6]])
b = a[0, 0]#使用整数索引
b = 2
b
2
a[0, 0]
1
print(a[0, 0] == b)
False

布尔索引

我们可以通过一个布尔数组来索引目标数组。

import numpy as np
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
y = x > 5
print(y)
[False False False False False  True  True  True]
#此处x>5代表直接取数组中大于数值5的元素值
print(x[x > 5])
[6 7 8]
x = np.array([np.nan, 1, 2, np.nan, 3, 4, 5])
#numpy.logical_not(x)返回X非逻辑后的布尔值。
y = np.logical_not(np.isnan(x))
print(x[y])
[1. 2. 3. 4. 5.]
x = np.array([[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]])
y = x > 25
print(y)
[[False False False False False]
 [False False False False False]
 [False False False False False]
 [ True  True  True  True  True]
 [ True  True  True  True  True]]
print(x[x>25])
[26 27 28 29 30 31 32 33 34 35]
  • 区别:当x > num单独出现时,会输出bool值,但当x > num作为索引出现时,会输出所有满足条件的值,并封装为一维数组
import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 50)
y = np.sin(x)
print(len(x))
50
plt.plot(y)
[<matplotlib.lines.Line2D at 0x184648f7808>]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NkGDbrAm-1603428241826)(output_64_1.png)]

plt.plot(x, y)
[<matplotlib.lines.Line2D at 0x1846496f808>]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CeMb0prv-1603428241830)(output_65_1.png)]

  • 两幅图对比可以看出x确定了横坐标的范围
mask = y >= 0
print(len(x[mask])) 
25
print(mask)
[ True  True  True  True  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True  True  True
  True False False False False False False False False False False False
 False False False False False False False False False False False False
 False False]
plt.plot(x[mask], y[mask], 'b')
[<matplotlib.lines.Line2D at 0x18464d4ba88>]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MNQYziGO-1603428241831)(output_69_1.png)]

plt.plot(x[mask], y[mask], 'bo')
[<matplotlib.lines.Line2D at 0x18464ee9648>]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mYRa8uLP-1603428241833)(output_70_1.png)]

plt.plot(x[mask], y[mask])
[<matplotlib.lines.Line2D at 0x184649a6a88>]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IWKYJNfo-1603428241834)(output_71_1.png)]

mask = np.logical_and(y >= 0, x <= np.pi / 2)
print(mask)
[ True  True  True  True  True  True  True  True  True  True  True  True
  True False False False False False False False False False False False
 False False False False False False False False False False False False
 False False False False False False False False False False False False
 False False]
plt.plot(x[mask], y[mask], 'go')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XlSQ3R4D-1603428241835)(output_73_0.png)]

数组迭代

x = np.array([[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]])
y = np.apply_along_axis(np.sum, 0, x)
print(y)
#对每一列求和
[105 110 115 120 125]
#对每一行求和
y = np.apply_along_axis(np.sum, 1, x)
print(y)
[ 65  90 115 140 165]
y = np.apply_along_axis(np.mean, 1, x)
print(y)
[13. 18. 23. 28. 33.]
def my_func(x):
    return (x[0] + x[-1]) * 0.5
y = np.apply_along_axis(my_func, 0, x)
print(y)
[21. 22. 23. 24. 25.]
y = np.apply_along_axis(my_func, 1, x)
y
array([13., 18., 23., 28., 33.])
print(y)
[13. 18. 23. 28. 33.]
y
array([13., 18., 23., 28., 33.])

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值