Numpy中B[i_b][ij_b]赋值无效?如何实现向量化数组修改?
NumPy布尔数组赋值失效问题:原因与向量化解决办法
为啥B[i_b][ij_b] = True改不动原数组?
在NumPy里,用整数数组(比如i_b)做索引属于高级索引,这种方式返回的是原数组的副本而非视图。你执行B[i_b][ij_b] = True时,第一步B[i_b]会生成一个包含B中第0、2、4行的临时副本,后续的[ij_b] = True只是修改了这个临时副本,原数组B完全没被改动,所以最终输出还是全False。
而循环里的B[i_b[k]][ij_b[k]],i_b[k]是单个整数,属于普通索引,返回的是原数组对应行的视图——视图相当于原数组的“别名”,修改视图会直接作用到原数组上,所以循环能生效。
不用循环,怎么实现向量化修改?
这里有几种高效的向量化方案:
方案1:先做掩码再批量赋值
先构造一个和B同形状的布尔掩码,标记出需要设为True的位置,再一次性完成赋值:
import numpy as np A = np.arange(50).reshape(5, 10) B = np.full(A.shape, False) i_b = np.array([0, 2, 4]) ij_b = A[i_b] % 2 == 0 # 构造掩码:先全为False,再把选中行的对应位置替换为ij_b的值 mask = np.zeros_like(B, dtype=bool) mask[i_b] = ij_b B[mask] = True print(B[i_b][ij_b]) # 输出全True
方案2:用np.ix_生成可广播索引
np.ix_可以将一维数组转换为可广播的多维索引,直接定位到目标位置完成赋值:
import numpy as np A = np.arange(50).reshape(5, 10) B = np.full(A.shape, False) i_b = np.array([0, 2, 4]) ij_b = A[i_b] % 2 == 0 # 用np.ix_把行索引和列索引转换成可广播的形状,直接赋值 B[np.ix_(i_b, np.arange(A.shape[1]))] = ij_b print(B[i_b][ij_b]) # 输出全True
方案3:提取扁平化的索引对
提取出所有需要修改的行、列索引对,再用二维索引直接赋值:
import numpy as np A = np.arange(50).reshape(5, 10) B = np.full(A.shape, False) i_b = np.array([0, 2, 4]) ij_b = A[i_b] % 2 == 0 # 重复行索引,匹配每一个需要修改的列位置 row_idx = np.repeat(i_b, np.sum(ij_b, axis=1)) # 提取所有需要修改的列索引 col_idx = np.where(ij_b)[1] # 直接给对应位置赋值 B[row_idx, col_idx] = True print(B[i_b][ij_b]) # 输出全True
内容的提问来源于stack exchange,提问作者Puco4
相关产品推荐
相关产品推荐

