第4章 NumPy基础:数组和矢量计算(Part2)
目录
NumPy的ndarray:一种多维数组对象
基本的索引和切片
一维数组
一维数组的索引和切片方式跟Python列表的差不多:
#code
data = np.arange(10)
print(data[4:7])
#output
[4 5 6]
比较有趣的是数组的赋值操作。当你将一个标量值赋值给一个切片时(如data[4 : 7] = 10),该值会自动传播到整个选区,这也是后面板块会讲到的广播:
#code
data = np.arange(10)
data[4:7] = 10
print(data)
#output
[ 0 1 2 3 10 10 10 7 8 9]
这是数组跟列表很重要的区别:数组切片是原始数组的视图。这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上(学到这里我已经震惊了:是我见识太少了没错,Python的功能强大程度远超我的想象)。这么做的原因是:NumPy的设计目的是处理大数据,假如NumPy坚持要将数据复制来复制去的话会产生何等的性能和内存问题。
当然,如果你想要得到的是ndarray切片的副本而非视图,就需要显式地进行复制操作:
#code
data = np.arange(10)
ans = data[4:7].copy()
ans[:] = 10
print(data)
#output
[0 1 2 3 4 5 6 7 8 9]
高维数组的元素索引
这里就拿二维数组来举例。在一个二维数组中,各索引位置上的元素不再是标量而是一维数组:
#code
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr2d[1])
#output
[4 5 6]
想要选取单个元素,有以下两种等价的方式:
#code
print(arr2d[0, 2])
#output
3
#code
print(arr2d[0][2])
#output
3
标量值和数组都可以被赋值给选取出来的元素:
#code
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
old_values = arr2d[0].copy()
arr2d[0] = 10
print(arr2d)
#output
[[10 10 10]
[ 4 5 6]
[ 7 8 9]]
#code
arr2d[0] = old_values
print(arr2d)
#output
[[1 2 3]
[4 5 6]
[7 8 9]]
高维数组的切片索引
高维度对象的花样更多,你可以在一个或多个轴上进行切片,也可以跟整数索引混合用。以上面那个二维数组arr2d为例:
#code
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr2d[:2])
#output
[[1 2 3]
[4 5 6]]
可以看出,它是沿着第一个轴切片的。你可以一次传入多个切片,就像传入多个索引一样:
#code
print(arr2d[:2, 1:])
#output
[[2 3]
[5 6]]
通过将整数索引和切片混合,可以得到低维度的切片:
#code
print(arr2d[1, 1:])
#output
[5 6]
同样,':'表示选取整个轴,因此可以如下操作对高维轴进行切片:
#code
print(arr2d[:, 1:])
#output
[[2 3]
[5 6]
[8 9]]
自然,对切片表达式的赋值操作也会被扩散到整个选区:
#code
arr2d[:2, 1:] = 0
print(arr2d)
#output
[[1 0 0]
[4 0 0]
[7 8 9]]