索引
一维索引
数组上的算术运算符会应用到 元素 级别。下面是创建一个新数组并填充结果的示例:
>>>import numpy as np
>>>A = np.arange(3,15) #array([ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>>A[0]
3
>>>A[1]
4
为了获取数组的末尾元素,可以使用负值索引
>>>A[-1]
14
>>>A[11]
14
二/多维索引
>>>B = np.arange(12).reshape(3,4)
'''array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])'''
>>>B[0]
array([0, 1, 2, 3])
>>>B[0][0]
0
>>>B[0,0] #与B[0][0]等价
0
逐行打印
for row in B:
print(row)
"""
[ 0, 1, 2, 3]
[ 4, 5, 6, 7]
[ 8, 9, 10, 11]
"""
逐列打印
如果要逐列打印,我们需要用到一点小trick,将B进行转置(B.T 即可完成),再打印
for column in B.T:
print(column)
"""
[0 4 8]
[1 5 9]
[2 6 10]
[3 7 11]
"""
逐元素打印
import numpy as np
A = np.arange(3,15).reshape((3,4))
print(A.flatten())
# array([3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
for item in A.flat:
print(item)
# 3
# 4
……
# 14
这一脚本中的flatten
是一个展开性质的函数,将多维的矩阵进行展开成1行的数列。而flat
是一个迭代器,本身是一个object
属性。
切片
正如此前用中括号获取单个数组元素,我们也可以用切片
(slice)符号获取子数组,切片符号用冒号(:)表示。NumPy切片语法和Python的标准切片语法相同。为了获取数组x的一个切片,可以采用如下方式:
x[start:stop:step]
即,从索引start开始,以step为步长,到stop为止,不包括stop
如果以上3个参数都未指定,那么它们将会被分别默认设置为start=0, stop=维度的大小(size of dimension)和step=1
1 一维子数组
>>>x = np.arange(10) #array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>>x[:5] #前5个元素
array([0, 1, 2, 3, 4])
>>>x[5:] #索引5之后的元素
array([5, 6, 7, 8, 9])
>>>x[4:7] #中间的子数组
array([4, 5, 6])
>>>x[::2] #每隔一个元素 或 理解为取偶数下标的元素
array([0, 2, 4, 6, 8])
>>>x[1::2] #每隔一个元素,从索引1开始
array([1, 3, 5, 7, 9])
步长为负值的情况
>>>x[::-1] #所有元素,逆序的
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
>>>x[5::-2] #从索引5开始,每隔一个元素逆序
array([5, 3, 1])
2 二/多维子数组
>>>x2 = np.array([[12,5,2,4],
[7,6,8,8],
[1,6,7,7]])
>>>x2[:2, :3] #前两行,前三列
array([[12, 5, 2],
[ 7, 6, 8]])
>>>x2[:3, ::2] #所有行,每隔一列
array([[12, 2],
[ 7, 8],
[ 1, 7]])
最后,子数组维度也可以同时被逆序
>>>x2[::-1, ::-1]
array([[ 7, 7, 6, 1],
[ 8, 8, 6, 7],
[ 4, 2, 5, 12]])
3 获取数组的行和列
一种常见的需求是获取数组的单行和单列。可以将索引与切片结合起来实现该功能,用一个冒号(:)表示空切片
>>>print(x2[:, 0]) #x2的第一列
[12 7 1]
>>>print(x2[0, :]) #x2的第一行
[12 5 2 4]
在获取行时,出于语法的简洁考虑,可以省略空的切片
>>>print(x2[0]) #等价于x2[0, :]
[12 5 2 4]
4 浅拷贝/视图
数组切片有一点非常重要,那就是数组切片返回的是数组数据的视图(浅拷贝),而不是数值数据的副本(深拷贝)
>>>x2_sub = x2[:2, :2]
array([[12, 5],
[ 7, 6]])
现在如果修改这个子数组,将会看到原始数组也被修改了!
>>>x2_sub[0,0] = 99
>>>print(x2_sub)
[[99 5]
[ 7 6]]
>>>print(x2)
[[99 5 2 4]
[ 7 6 8 8]
[ 1 6 7 7]]
5 深拷贝/副本
>>>x2_sub = x2[:2, :2].copy()
array([[12, 5],
[ 7, 6]])
如果修改这个子数组,原始数组不会被改变
>>>x2_sub[0,0] = 44
>>>print(x2_sub)
[[44 5]
[ 7 6]]
>>>print(x2)
[[12 5 2 4]
[ 7 6 8 8]
[ 1 6 7 7]]