如何通过行和列索引将NumPy二维数组的指定块置零?
如何通过行和列索引将NumPy二维数组的指定块置零?
嘿,我完全懂你遇到的困扰!你想把指定行和列的所有交叉区域都置零,但之前尝试的两种写法都没达到预期效果,咱们来拆解问题并找到简洁的解决办法。
首先,先说说你之前两种写法为什么不行:
- 第一种写法
a[indices, indices] = 0.0:当你给NumPy传入两个一维索引数组时,它会执行配对索引,也就是只会选取(indices[0], indices[0])、(indices[1], indices[1])这类对角位置的元素,所以只有对角线上的值被置零了,这和你要的交叉块效果不符。 - 第二种写法
a[indices, :][:, indices] = 0.0:a[indices, :]会返回原数组的一个副本(不是视图),你后续对这个副本的切片赋值操作,根本不会影响到原数组,所以原数组完全没变化。
正确的解决方法
NumPy其实专门提供了处理这种“交叉块索引”的工具,这里有两种高效的写法:
方法1:使用np.ix_生成网格索引
np.ix_函数的作用就是把一维索引转换成可以广播的二维索引网格,刚好能满足你的需求:
import numpy as np a = np.ones((6, 8)) indices = [2, 3, 5] # 用np.ix_构造交叉索引 a[np.ix_(indices, indices)] = 0.0 print(a)
运行这段代码后,就能得到你期望的结果:
[[1. 1. 1. 1. 1. 1. 1. 1.] [1. 1. 1. 1. 1. 1. 1. 1.] [1. 1. 0. 0. 1. 0. 1. 1.] [1. 1. 0. 0. 1. 0. 1. 1.] [1. 1. 1. 1. 1. 1. 1. 1.] [1. 1. 0. 0. 1. 0. 1. 1.]]
方法2:手动构造广播索引
如果你不想用np.ix_,也可以通过手动调整数组形状来实现广播索引:
# 将行索引转为二维列向量,和列索引广播生成网格 a[np.array(indices)[:, None], indices] = 0.0
这里np.array(indices)[:, None]把一维的indices转换成了形状为(3,1)的二维数组,和原一维的indices(形状(3,))广播后,就会生成覆盖所有交叉位置的索引网格,效果和np.ix_完全一致。
关于大数组的性能
这两种方法都非常适合你提到的90k×90k的大数组,因为它们都是直接对原数组进行操作,没有创建不必要的中间副本,效率远高于循环或者生成所有组合索引的方式,能快速完成置零操作。
备注:内容来源于stack exchange,提问作者mightypile
相关产品推荐
相关产品推荐

