Numpy高级索引
整数数组索引
import numpy as np
x = np.array([[1, 2], [3, 4], [5, 6]])
y = x[[0,1,2], [0,1,0]]
y
# array([1, 4, 5])
import numpy as np
a = np.array([[1,2,3], [4,5,6],[7,8,9]])
b = a[1:3, 1:3]
c = a[1:3,[1,2]]
d = a[...,1:]
print(b)
print(c)
print(d)
#[[5 6]
# [8 9]]
#[[5 6]
# [8 9]]
#[[2 3]
# [5 6]
# [8 9]]
布尔索引
import numpy as np
x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]])
print ('大于 5 的元素是:')
x[x > 5]
# 大于 5 的元素是:
# array([ 6, 7, 8, 9, 10, 11])
# 使用 ~(取补运算符)来过滤 NaN
import numpy as np
a = np.array([np.nan, 1,2,np.nan,3,4,5])
a[~np.isnan(a)]
# array([1., 2., 3., 4., 5.])
# 过滤掉非复数元素
a = np.array([1, 2+6j, 5, 3.5+5j])
a[np.iscomplex(a)]
# array([2. +6.j, 3.5+5.j])
a = np.array([1, 2+6j, 5, 3.5+5j])
a[~np.iscomplex(a)]
# array([1.+0.j, 5.+0.j])
花式索引
# 传入顺序索引数组
import numpy as np
x=np.arange(32).reshape((8,4))
x[[4,2,1,7]]
# array([[16, 17, 18, 19],
# [ 8, 9, 10, 11],
# [ 4, 5, 6, 7],
# [28, 29, 30, 31]])
# 传入倒序索引数组
x=np.arange(32).reshape((8,4))
x[[-4,-2,-1,-7]]
#array([[16, 17, 18, 19],
# [24, 25, 26, 27],
# [28, 29, 30, 31],
# [ 4, 5, 6, 7]])
# 传入多个索引数组(要使用np.ix_)
x=np.arange(32).reshape((8,4))
x[np.ix_([1,5,7,2],[0,3,1,2])]
# array([[ 4, 7, 5, 6],
# [20, 23, 21, 22],
# [28, 31, 29, 30],
# [ 8, 11, 9, 10]])
NumPy 广播(Broadcast)
# 如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape,那么 a*b 的结果就是 a 与 b 数组对应位相乘。
a = np.array([1,2,3,4])
b = np.array([10,20,30,40])
c = a * b
c
# array([ 10, 40, 90, 160])
# 当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制。
a = np.array([[ 0, 0, 0],
[10,10,10],
[20,20,20],
[30,30,30]])
b = np.array([0,1,2])
a + b
# array([[ 0, 1, 2],
# [10, 11, 12],
# [20, 21, 22],
# [30, 31, 32]])
a = np.array([[ 0, 0, 0],
[10,10,10],
[20,20,20],
[30,30,30]])
b = np.array([1,2,3])
bb = np.tile(b, (4, 1)) # 重复 b 的各个维度
a + bb
# array([[ 1, 2, 3],
# [11, 12, 13],
# [21, 22, 23],
# [31, 32, 33]])
NumPy 迭代数组
NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式
import numpy as np
a = np.arange(6).reshape(2,3)
for x in np.nditer(a):
print (x, end=", " )
print ('\n')
# 0, 1, 2, 3, 4, 5,
a = np.arange(6).reshape(2,3)
# 选择的顺序是和数组内存布局一致的,这样做是为了提升访问的效率,默认是行序优先
for x in np.nditer(a.T):
print (x, end=", " )
print ('\n')
# a.T.copy(order = 'C') 的遍历结果默认是按行访问
for x in np.nditer(a.T.copy(order='C')):
print (x, end=", " )
print ('\n')
# 0, 1, 2, 3, 4, 5,
# 0, 3, 1, 4, 2, 5,
控制遍历顺序
for x in np.nditer(a, order='F') #:Fortran order,即是列序优先;
for x in np.nditer(a.T, order='C') #:C order,即是行序优先;
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('以 C 风格顺序排序:')
for x in np.nditer(a, order = 'C'):
print (x, end=", " )
print ('以 F 风格顺序排序:')
for x in np.nditer(a, order = 'F'):
print (x, end=", " )
原始数组是:
[[ 0 5 10 15]
[20 25 30 35]
[40 45 50 55]]
以 C 风格顺序排序:
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55,
以 F 风格顺序排序:
0, 20, 40, 5, 25, 45, 10, 30, 50, 15, 35, 55,
修改数组中元素的值
nditer
对象有另一个可选参数 op_flags
。 默认情况下,nditer
将视待迭代遍历的数组为只读对象(read-only
),为了在遍历数组的同时,实现对数组元素值得修改,必须指定 read-write
或者 read-only
的模式。
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
for x in np.nditer(a, op_flags=['readwrite']):
x[...]=2*x
print ('修改后的数组是:')
print (a)
# 原始数组是:
#[[ 0 5 10 15]
# [20 25 30 35]
# [40 45 50 55]]
#修改后的数组是:
#[[ 0 10 20 30]
# [ 40 50 60 70]
# [ 80 90 100 110]]
使用外部循环
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('修改后的数组是:')
for x in np.nditer(a, flags = ['external_loop'], order = 'F'):
print (x, end=", " )
# 原始数组是:
#[[ 0 5 10 15]
# [20 25 30 35]
# [40 45 50 55]]
# 修改后的数组是:
#[ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55],
广播迭代
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
b = np.array([1, 2, 3, 4], dtype = int)
for x,y in np.nditer([a,b]):
print ("%d:%d" % (x,y), end=", " )
# 0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4,