Python 2中以最Pythonic方式向ndarray子数组写入数据
解决NumPy子矩阵批量修改的问题
为什么你的首次尝试没生效?
你第一次用a[rows_to_keep,:][:,columns_to_keep] = ...修改原数组失败,核心原因是:当你用整数数组索引(比如rows_to_keep = [0,1])选取行时,NumPy返回的是原数组的副本而非视图。后续的[:,columns_to_keep]操作都是在这个临时副本上进行的,修改的只是副本,原数组a自然不会有任何变化。
正确的批量修改方法:用np.ix_构造索引网格
要实现子矩阵的高效批量修改,你可以用np.ix_()函数来构造正确的索引。它能把一维的行、列索引数组转换成可选中二维子矩阵的索引网格,让赋值操作直接作用在原数组上——完全不需要循环,且支持连续/非连续的行、列索引,非常适合后续扩展。
示例1:修改连续行+连续列的子矩阵
import numpy as np # 初始化原数组 number_of_rows = 3 number_of_columns = 3 a = np.arange(number_of_rows*number_of_columns).reshape(number_of_rows,number_of_columns) # 定义要修改的行、列索引和新值 rows_to_keep = [0,1] columns_to_keep = [1,2] new_values = np.asarray([[100,101],[102,103]]) # 核心操作:用np.ix_构造索引并赋值 a[np.ix_(rows_to_keep, columns_to_keep)] = new_values print(a)
输出结果:
array([[0, 100, 101], [3, 102, 103], [6, 7, 8]])
示例2:修改非连续行+非连续列的子矩阵
# 重新初始化数组 a = np.arange(number_of_rows*number_of_columns).reshape(number_of_rows,number_of_columns) # 定义非连续的行、列索引和新值 rows_to_keep = [0,2] columns_to_keep = [0,2] new_values = np.asarray([[100,101],[102,103]]) # 同样用np.ix_构造索引赋值 a[np.ix_(rows_to_keep, columns_to_keep)] = new_values print(a)
输出结果:
array([[100, 1, 101], [3, 4, 5], [102, 7, 103]])
原理补充:np.ix_做了什么?
np.ix_会把一维的行索引数组(比如[0,1])转换成二维列向量[[0],[1]],把一维的列索引数组(比如[1,2])转换成二维行向量[[1,2]]。通过NumPy的广播机制,这两个数组会生成一个2x2的索引网格,正好对应你要修改的子矩阵的每个位置,从而实现精准的批量赋值。
如果你不想用np.ix_,也可以手动构造二维索引,效果完全一致:
a[rows_to_keep[:, np.newaxis], columns_to_keep] = new_values
不过np.ix_的写法更直观易读,推荐使用。
内容的提问来源于stack exchange,提问作者Rafael Valero
相关产品推荐
相关产品推荐

