前言
- 索引指的是用方括号 “[ ]” 加序号的形式引用数组中特定位置的元素,它的作用是从数组中取出一部分相应的元素重新组成一个子数组,而这个子数组就是通过索引得到的切片。
一、副本与视图
- 在Numpy中做数组运算时,返回的结果只有两种,一是“视图”,二是“副本”。
import numpy as np
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
y = x # 创建视图
y[0] = -1
print(x)
# [-1 2 3 4 5 6 7 8]
print(y)
# [-1 2 3 4 5 6 7 8]
# 此处改变视图y,原数组x也随之改变
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
y = x.copy() # 创建副本
y[0] = -1
print(x)
# [1 2 3 4 5 6 7 8]
print(y)
# [-1 2 3 4 5 6 7 8]
# 此处改变副本y,原数组x不变
- 从上例可知,对副本数据进行修改,不会影响到原始数据,这是因为他们物理内存不在同一位置;而对视图数据进行修改,原始数据也会随之改变,这是因为视图数据与原始数据物理内存在同一位置。
- 此处用到了一个函数:
numpy.copy()
其作用就是为原始数据创建一个副本。
二、索引与切片
1.整数索引
- 获取数组的单个元素,多维数组的子数组。
import numpy as np
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
print(x[6]) # 7
x = np.array([[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25],
[12, 34, 56, 78, 99],
[31, 32, 33, 34, 35]])
print(x[1]) # [16, 17, 18, 19, 20]
print(x[3][2]) # 33
print(x[3, 2]) # 33
2.切片索引
- 切片即从数组中抽取一部分元素组成新的数组。
- 对Python 列表 进行切片操作,得到的数组是原数组的 副本,即修改切片后,原数组不变。
- 对Numpy数据进行切片操作,得到的数组是指向相同缓冲区的 视图。
- 一维数组
import numpy as np
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
# 起始位置索引为1,结束位置索引为5,间隔为2
print(x[1:5:2]) # [2 4]
# 若不写间隔,则默认为1
print(x[0:4]) # [1 2 3 4]
# 若不写结束位置索引,则默认为最大索引值
print(x[2:]) # [3 4 5 6 7 8]
# 若不写起始位置索引,则默认为0
print(x[:2]) # [1 2]
# 若起始、结束位置索引均不写,则取全部
print(x[:]) # [1 2 3 4 5 6 7 8]
# 若索引值为负,则最大索引值为-1,依次向前递减
print(x[-2:]) # [7 8]
print(x[:-2]) # [1 2 3 4 5 6]
# 利用负数下标翻转数组
print(x[::-1]) # [8 7 6 5 4 3 2 1]
- 二维数组,切片的第一片定义了行的切片,第二片定义了列的切片。
import numpy as np
x = np.array([[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]])
print(x[2:4])
# [[11 12 13 14 15]
# [16 17 18 19 20]]
print(x[1:5:2])
# [[6 7 8 9 10]
# [16, 17, 18, 19, 20]]
print(x[2:])
# [[11, 12, 13, 14, 15],
# [16, 17, 18, 19, 20],
# [21, 22, 23, 24, 25]]
print(x[:2])
# [[11 12 13 14 15]
# [16 17 18 19 20]]
print(x[-2:])
# [[16, 17, 18, 19, 20],
# [21, 22, 23, 24, 25]]
print(x[:-2])
# [[1, 2, 3, 4, 5],
#[6, 7, 8, 9, 10],
# [11, 12, 13, 14, 15]]
print(x[:])
# [[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]]
# 输出第二行数据
print(x[1, :]) # [6 7 8 9 10]
# 输出第二列数据
print(x[:, 1]) # [2 7 12 17 22]
# 输出第1行,第2到4个数据
print(x[0, 1:4]) # [2 3 4]
# 输出第1列,第2到4个数据
print(x[1:4, 0]) # [6 11 16]
print(x[1:3, 2:4])
# [[8 9]
# [13 14]]
print(x[:, :]) # 效果与x[:]一样
# 行,列,间隔均为2
print(x[::2, ::2])
# [[1 3 5]
# [11 13 15]
# [21 23 25]]
# 从0行开始,间隔2行赋值;从1列开始,间隔3列赋值
x[0::2, 1::3] = 0
print(x)
# [[1 0 3 4 0]
# [6 7 8 9 10]
# [11 0 13 14 0]
# [16 17 18 19 20]
# [21 0 23 24 0]]
# 所有行颠倒顺序
print(x[::-1, :])
# 所有列颠倒顺序
print(x[:, ::-1])
3.整数数组索引
- 方括号内传入多个索引值,可以同时选择多个元素。
- 一维数组:
import numpy as np
# 从一维数组中抽取特殊点
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
r = [0, 1, -1]
print(x[r]) # [1 2 8]
# 从一维数组中抽取特殊点组成二维数组
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
r = np.array([[0, 1], [3, 4], [6, 7])
print(x[r])
# [[1 2]
# [4 5]
# [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]])
r = [0, 1, -1]
print(x[r])
# [[11 12 13 14 15]
# [16 17 18 19 20]
# [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]])
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 = [0, 1, 2]
c = [2, 3, 4]
y = x[r, c] # r,c均为一维数组,故y也为一维数组
print(y) # [13 19 25]
# 从二维数组中抽取特殊点组成二维数组
r = np.array([[0, 0], [4, 4]])
c = np.array([[0, 4], [0, 4]])
y = x[r, c] # r,c均为二维数组,故y也为二维数组
print(y)
# [[11 15]
# [31 35]]
- 特殊函数
numpy.take()
import numpy as np
# 一维数组
x = np.array([1, 2, 3, 4, 5, 6, 7, 8])
r = [0, 1, 2]
print(np.take(x, r)) # [1 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]])
r = [0, 1, 2]
print(np.take(x, r, axis=0)) # 输出特定行
# [[11 12 13 14 15]
# [16 17 18 19 20]
# [21 22 23 24 25]]
print(np.take(x, r, axis=1)) # 输出特定列
# [[11 12 13]
# [16 17 18]
# [21 22 23]
# [26 27 28]
# [31 32 33]]
4.布尔索引
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]
print(x[x > 5]) # [6 7 8]
x = np.array([1, 9, np.nan, 3, 4, np.nan, 0])
y = np.logical_not(np.isnan(x)) # 逻辑非
print(x[y]) # [1. 9. 3. 4. 0.]
# 二维数组变一维数组
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]
三、补充知识
1.数组迭代
- 本块介绍函数
np.apply_along_axis()
import numpy as np
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, 0, x)
print(y) # [21. 22. 23. 24. 25.]
# 每行求平均
y = np.apply_along_axis(np.mean, 1, x)
print(y) # [13. 18. 23. 28. 33.]
2.array换行、换列
import numpy as np
A = np.arange(9).reshape(3, 3)
print(A)
# [[0 1 2]
# [3 4 5]
# [6 7 8]]
# 列列互换
B = A[:, [2, 1, 0]]
print(B)
# [[2 1 0]
# [5 4 3]
# [8 7 6]]
# 行行互换
C = A[[1, 0, 2], :]
print(C)
# [[3 4 5]
# [0 1 2]
# [6 7 8]]