Numpy 中多维数组的切⽚操作与Python
numpy在处理数据的时候,经常会有切⽚操作,如提取指定⼏⾏的数据或者⼏列的数据,本⽂记录⼀些典型的切⽚⽅法以备⽇后查看。⼀维数组的切⽚:
数组[start:end:step]
从start到end,以step为步长的元素
且:start < end.
1
2
3
正向
正向第i个元素到第j个元素:1
2
3
4
返回b[i],b[i+1],···,b[j-1]的元素
1
2
3
4
我们发现是左闭右开,第j个元素不返回。
1
2
以2位步长,取下标为2的倍数的元素。
反向
反向 倒数⼏个元素: start和end为负数则是反向取元素,
取b[start+1]b[start+1] ,b[start+2],···,b[end]的元素
>>> b=np.random.randint(1,10,[10])
>>> b array([6, 5, 2, 3, 9, 9, 3, 8, 5, 8])
>>> i=1
>>> j=8
>>> b[i:j]array([5, 2, 3, 9, 9, 3, 8])
>>> i=1
>>> j=2
>>> b[i:j]array([5])
>>> b[::2]
array([6, 2, 9, 3, 5])
>>> b[-3:-1]
array([8, 5])
1
2
⼆维数组的切⽚
>>> a=np.random.randint(0,10,size=[4,5])
>>> a
array([[1, 8, 4, 9, 8],
[4, 1, 6, 4, 2],
[6, 4, 1, 2, 7],
[4, 9, 3, 5, 9]])
1
2
3
4
5
6
取 第i⾏到第j⾏:
>>> a[2:4,:]
array([[6, 4, 1, 2, 7],
[4, 9, 3, 5, 9]])
1
2
3
第i列到第j列:
>>> a[:,2:4]
array([[4, 9],
[6, 4],
[1, 2],
[3, 5]])
1
2
3
4
5
我们可以发现,多维的切⽚是在中括号中⽤逗号运算符, 将不同维上的操作分开,分割开后每个维度上单独维护即可。另外
另外 numpy中对切⽚元素的操作是会影响到原数组本⾝的!
例如沿⽤上例的a矩阵:
>>> a[:1,:1]=[[100]]
>>> a
array([[100,  8,  4,  9,  8],
[  4,  1,  6,  4,  2],
[  6,  4,  1,  2,  7],
[  4,  9,  3,  5,  9]])
切⽚(slicing)操作
Numpy 中多维数组的切⽚操作与 Python 中 list 的切⽚操作⼀样,同样由 start, stop, step 三个部分组成import numpy as np
arr = np.arange(12)
print'array is:', arr
slice_one = arr[:4]
print'slice begins at 0 and ends at 4 is:', slice_one
slice_two = arr[7:10]
print'slice begins at 7 and ends at 10 is:', slice_two
slice_three = arr[0:12:4]
print'slice begins at 0 and ends at 12 with step 4 is:', slice_three
array is: [ 0  1  2  3  4  5  6  7  8  9 10 11]
slice begins at 0 and ends at 4 is: [0 1 2 3]
slice begins at 7 and ends at 10 is: [7 8 9]
slice begins at 0 and ends at 12 with step 4 is: [0 4 8]
上述例⼦是⼀维数组的例⼦,如果是多维数组,将不同维度上的切⽚操作⽤逗号分开就好了
# coding: utf-8
import numpy as np
arr = np.arange(12).reshape((3, 4))
print'array is:'
print arr
# 取第⼀维的索引 1 到索引 2 之间的元素,也就是第⼆⾏
# 取第⼆维的索引 1 到索引 3 之间的元素,也就是第⼆列和第三列
slice_one = arr[1:2, 1:3]
print'first slice is:'
print slice_one
# 取第⼀维的全部
# 按步长为 2 取第⼆维的索引 0 到末尾之间的元素,也就是第⼀列和第三列
slice_two = arr[:, ::2]
print'second slice is:'
print slice_two
array is:
[[ 0  1  2  3]
[ 4  5  6  7]
[ 8  9 10 11]]
first slice is:
[[5 6]]
second slice is:
[[ 0  2]
[ 4  6]
[ 8 10]]
对于 slice_two,如果 arr 是⽤ Python 的 list 表⽰的,那么要得到相同的结果得像下⾯这样,相对来说就⿇烦多了: import numpy as np
arr = np.arange(12).reshape((3, 4)).tolist()
slice_two = [
row[::2] for row in arr
]
print slice_two
[[0, 2], [4, 6], [8, 10]]
对于维数超过 3 的多维数组,还可以通过 '…' 来简化操作
# coding: utf-8
import numpy as np
arr = np.arange(24).reshape((2, 3, 4))
print arr[1, ...]              # 等价于 arr[1, :, :]
print arr[..., 1]              # 等价于 arr[:, :, 1]
[[12 13 14 15]
[16 17 18 19]
[20 21 22 23]]
[[ 1  5  9]
[13 17 21]]
索引(indexing) 操作
最简单的情况
对于⼀个多维数组来说,最简单的情况就是访问其中⼀个特定位置的元素了,如下所⽰:
# coding: utf-8
import numpy as np
arr = np.array([
[1, 2, 3, 4],
[2, 4, 6, 8],
[3, 6, 9, 12],
[4, 8, 12, 16]
])
print'第⼆⾏第⼆列的值:', arr[1, 1]
第⼆⾏第⼆列的值: 4
相⽐之下,如果⽤ Python 的 list 来表⽰上述⼆维数组,获取同⼀个位置的元素的⽅法为:
# coding: utf-8
arr = [
[1, 2, 3, 4],
[2, 4, 6, 8],
[3, 6, 9, 12],
python获取数组长度[4, 8, 12, 16]
]
print'第⼆⾏第⼆列的值:', arr[1][1]
try:
print'第⼆⾏第⼆列的值(尝试⽤ Numpy 的⽅式获取):', arr[1, 1]
except Exception as e:
print str(e)
第⼆⾏第⼆列的值: 4
第⼆⾏第⼆列的值(尝试⽤ Numpy 的⽅式获取): list indices must be integers, not tuple
如果只是⼆维数组,这种差别可能看起来并不⼤,但想象⼀下假如有⼀个 10 维的数组,⽤ Python 的标准做法需要写 10 对中括号,⽽⽤Numpy 依然只需要⼀对。
获取多个元素
事实上,在 Numpy 的索引操作⽅式 `x = arr[obj]` 中, obj 不仅仅可以是⼀个⽤逗号分隔开的数字序列,还可以是更复杂的内容。
1. ⽤逗号分隔的数组序列
1. 序列的长度和多维数组的维数要⼀致
2. 序列中每个数组的长度要⼀致
import numpy as np
arr = np.array([
[1, 2, 3, 4],
[2, 4, 6, 8],
[3, 6, 9, 12],
[4, 8, 12, 16]
])
print arr[[0, 2], [3, 1]]
[4 6]
以上⾯这个例⼦来说,其含义是: 选择第⼀⾏和第三⾏,然后对第⼀⾏选择第四列,对第三⾏选择第⼆列。
2. boolean/mask index
这个不太好翻译,所以就⽤原来的英语表达。
所谓 boolean index,就是⽤⼀个由 boolean 类型值组成的数组来选择元素的⽅法。⽐如说对下⾯这样多维数组
array([[1, 2, 3, 4],
[2, 4, 6, 8],
[3, 6, 9, 12],
[4, 8, 12, 16]])
如果要取其中值⼤于 5 的元素,就可以⽤上 boolean index 了,如下所⽰: