numpy-索引和遍历

索引和遍历

NumPy 的切片创建了 view 而不是像内置的python序列(如string、tuple和list)那样的副本。在从大型数组中提取一小部分时必须小心,因为提取的小部分包含对大型原始数组的引用,在对其派生的所有数组进行垃圾收集之前,不会释放这些数组的内存。在这种情况下, copy() 建议使用。

  • 当切片的数量少于数组维度时,缺失的维度索引被认为是一个完整切片, 省略与使用“:”或“…”等价

基础索引

一维数组

一维数组的索引和 Python 中 list 结构索引十分相似,需要注意在切片索引的时候末尾的下标是取不到

a = np.array([0, 1, 2, 3, 4, 5])
print(type(a))
print(a[0])  # 0
print(a[2:4])  # [2 3]
print(a[1:3])  # [1 2]
print(a[1:5:2])  # [1 3]

二维数组

切片和索引
a = np.arange(12).reshape(3, 4)
print(a[2][0])  #8 
print(a[2,0])   #8
#第一种方式通过递归访问,首先a[2]将得到array([8, 9, 10, 11]),然后a[2][0]访问索引为0的数字,得到8;如果对数组的大小理解清楚了,那么第二种方式就是非常直接的指定了该数据在第0轴的索引2位置和第1轴的索引0位置。

a = np.array([[1,2,3,4,5],[6,7,8,9,10]])
print(a[0:1]) #截取第一行,返回 [[1 2 3 4 5]]
print(a[1,2:5]) #截取第二行,第三、四、五列,返回 [8 9 10]
print(a[1,:]) #截取第二行,返回 [ 6  7  8  9 10]

不同行,采用 ,  隔开
同一行满足列表索引规则
arr_2d = np.arange(16).reshape(4,4)
print(arr_2d)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]
#  [12 13 14 15]]

print(arr_2d[0, 1:3])
print(arr_2d[0:2, 1:3])

# [1 2]
# [[1 2]
#  [5 6]]

print(arr_2d[:, 1:3])
#[[ 1  2]
# [ 5  6]
# [ 9 10]
# [13 14]]
a = np.array([[1,2,3],[3,4,5],[4,5,6]])   

# 第2列元素
print(a[...,1])   

# 第2行元素 
print(a[1,...])

# 第2列及剩下的所有元素
print(a[...,1:])

#[2 4 5]
#[3 4 5]
#[[2 3] 
# [4 5] 
# [5 6]]

高级索引

使用索引数组进行索引

a = np.arange(5,16)

print(a[[0, 1]])  # [5 6]
print(a[np.array([[0, 1]])])   # [[5 6]]
print(a[np.array([[0, 1], [2, 3]])])  # [[5 6] [7 8]]

#---------------------------------------------------------------
#取值矩阵的四个角
x = np.array([[  0,  1,  2],[  3,  4,  5],[  6,  7,  8],[  9,  10,  11]])   

print(x) 
rows = np.array([[0,0],[3,3]]) 
cols = np.array([[0,2],[0,2]])
y = x[rows,cols]  
print(y)


#[[ 0  1  2] 
# [ 3  4  5] 
# [ 6  7  8] 
# [ 9 10 11]]

#[[ 0  2]
# [ 9 11]]


使用布尔值数组进行索引

#获取大于 5 的元素
x = np.array([[  0,  1,  2],[  3,  4,  5],[  6,  7,  8],[  9,  10,  11]])   
print(x)
# 现在我们会打印出大于 5 的元素
print(x[x>5])
#[[ 0  1  2]
# [ 3  4  5]
# [ 6  7  8]
# [ 9 10 11]]

#[ 6  7  8  9 10 11]

#---------------------------------------------------------------
zarten = np.random.randn(5,4)
print(zarten)
print('')

zarten_bool = np.array([True, False, False, False, True])
print(zarten[zarten_bool])

#[[0.12370779 0.60020841]
# [0.19022537 0.65618376]
# [0.5231678  0.18813379]
# [0.53643122 0.26875578]
# [0.55525969 0.23672487]]

#[[0.12370779 0.60020841]
# [0.55525969 0.23672487]]

zarten_1 = np.array(['A', 'B', 'C', 'D', 'A'])
print(zarten[zarten_1 == 'A'])     # != 不等于,& 与运算,| 或运算
#[[0.12370779 0.60020841]
# [0.55525969 0.23672487]]
#---------------------------------------------------------------
#~(取反运算符)来过滤 NaN
a = np.array([np.nan,  1,2,np.nan,3,4,5])
print(a[~np.isnan(a)])

#---------------------------------------------------------------
a = np.array(['www', 'finthon', 'com'])
b = np.arange(12).reshape(3, 4)
print(b[a == 'finthon'])
#[[4 5 6 7]]

花式索引

是利用整数数组进行行索引的方式

a = np.arange(12).reshape(3, 4)
print(a)
b = a[[2, 0, 1]]  # 一维整数数组, 针对的是 0 维度
print(b)
#[[ 0  1  2  3]
# [ 4  5  6  7]
# [ 8  9 10 11]]

#[[ 8  9 10 11]
# [ 0  1  2  3]
# [ 4  5  6  7]]

c=a[[1, 1, 2, 2], [1, 3, 0, 2]] # 二维整数数组,针对的是两个维度
print(c) 
# [ 5  7  8 10]

np.ix_()函数

np.ix_()函数,能把两个一维数组 转换为 一个用于选取方形区域的索引器

a = np.arange(10).reshape(2, 5)
b=a[[0,1],[2,4]]                    #整数数组索引
c=a[np.ix_([0, 1], [2, 4])]         #np.ix_() 整数数组索引
print(b)
print(c)

#[2 9]
#[[2 4]
# [7 9]]

d=a[[True, True], [2, 4]]
e=a[np.ix_([True, True], [2, 4])]
print(d)
print(e)

#[2 9]
#[[2 4]
# [7 9]]

np.where()

np.where(condition, [x, y])必写参数是condition(判断条件),后边的x和y是可选参数

  • 当where内只有一个参数时,那个参数表示条件,当条件成立时,where返回的是每个符合condition条件元素的坐标,返回的是以元组的形式

  • 当where内有三个参数时,第一个参数表示条件,当条件成立时where方法返回x,当条件不成立时where返回y

其实你不应该在这个目录分区里

a = np.array([2, 4, 6, 8, 10])
print(a)
print(np.where(a > 5))
print(a[np.where(a > 5)])
#[ 2  4  6  8 10]
#(array([2, 3, 4], dtype=int64),)
#[ 6  8 10]

#---------------------------------------------------------------
x= np.random.randint(0,4,size=(3,3))
print(x)

print(np.where(x>2))

#[[0 2 1]
# [0 1 3]
# [3 1 0]]
#(array([1, 2], dtype=int64), array([2, 0], dtype=int64))

print(np.where(x==2))
(array([0], dtype=int64), array([1], dtype=int64))

#---------------------------------------------------------------
a = np.arange(10)
print(a)
aa = np.where(a, 1, -1)
print(aa)
aaa = np.where(a > 5, 5, -5)
print(aaa)

#[0 1 2 3 4 5 6 7 8 9]
#[-1  1  1  1  1  1  1  1  1  1]
#[-5 -5 -5 -5 -5 -5  5  5  5  5]

Numpy数组遍历

按照内存布局打印数组元素

numpy.nditer 迭代器返回的元素顺序,是和数组内存布局一致的,这样做是为了提升访问的效率,默认是行序优先

arr = np.arange(6).reshape(2,3)
for i in np.nditer(arr):
    print(i, end=" ")
    
#0 1 2 3 4 5

#---------------------------------------------------------------
#默认的打印顺序是行序优先   order="C"
for i in np.nditer(arr.T):
    print(i, end=" ")
#0 1 2 3 4 5

#控制遍历顺序

print ('以 F 风格顺序排序:')
for i in np.nditer(arr, order="F"):
    print(i, end=" ")

# 可选参数 op_flags  默认 迭代遍历的数组为只读对象(read-only)

arr1 = np.arange(8).reshape(2,4)
for i in np.nditer(arr1, op_flags=["readwrite"]):
    i[...] = i**2
    
#[[ 0  1  4  9]
# [16 25 36 49]]
# flags 参数可以接受传入一个数组或元组,它可以接受下列值
    
参数 描述
c_index 可以跟踪 C 顺序的索引
f_index 可以跟踪 Fortran 顺序的索引
multi-index 每次迭代可以跟踪多重索引类型
external_loop 给出的值是具有多个值的一维数组,而不是零维数组
#设置 flags=["c_index"],可以实现类似 list 的 enumerate 函数的效果
cit =  np.nditer(arr, flags=["c_index"])
while not cit.finished:
    print("value:", cit[0], "index:<{}>".format(cit.index))
    cit.iternext()
# value: 0 index:<0>
# value: 1 index:<1>
# value: 2 index:<2>
# value: 3 index:<3>
# value: 4 index:<4>
# value: 5 index:<5>
# value: 6 index:<6>
# value: 7 index:<7>   
 
#---------------------------------------------------------------
mul_it = np.nditer(arr, flags=['multi_index'])

while not mul_it.finished:
    print("value:", mul_it[0], "index:<{}>".format(mul_it.multi_index))
    mul_it.iternext()

# value: 0 index:<(0, 0)>
# value: 1 index:<(0, 1)>
# value: 2 index:<(0, 2)>
# value: 3 index:<(0, 3)>
# value: 4 index:<(1, 0)>
# value: 5 index:<(1, 1)>
# value: 6 index:<(1, 2)>
# value: 7 index:<(1, 3)>
posted @ 2021-08-04 08:59  贝壳里的星海  阅读(761)  评论(0编辑  收藏  举报