如何利用索引数组与值数组快速更新Numpy数组?可换数据结构
快速更新Numpy数组的高效方法
一、最优方案:Numpy矢量化索引赋值
你当前的Python循环是效率瓶颈,Numpy原生支持批量索引赋值,完全不需要循环,底层用C实现,速度提升非常明显。
直接替换你的循环代码:
import numpy as np a = np.ones([5,5]) print("初始数组a:\n", a) b = np.array([[1,1], [2,2], [4,4]]) c = [10,10,10] # 批量赋值,一步完成 a[b[:, 0], b[:, 1]] = c print("更新后的数组a:\n", a)
原理:
b[:, 0]提取所有索引对的行号,得到一维数组[1,2,4]b[:, 1]提取所有索引对的列号,得到一维数组[1,2,4]- Numpy会将这两个数组对应位置的元素作为坐标,直接给
a的对应位置赋值,这是矢量化操作,避免了Python循环的开销。
二、关于是否使用字典
如果你的索引是离散、非结构化的,且需要频繁的键值查找,字典可能有适用场景,但对于二维数组的批量更新,字典反而不如Numpy高效。
比如用字典存储索引和值,最终还是需要遍历字典赋值:
idx_dict = {(1,1):10, (2,2):10, (4,4):10} for (i,j), val in idx_dict.items(): a[i,j] = val
这种方式本质还是Python循环,效率和你原来的代码差不多,甚至因为字典的键解析额外开销,速度更慢。
三、性能对比(示例)
当索引数量很大时,矢量化的优势会非常显著,比如用timeit测试:
import timeit def loop_assign(a, b, c): for i in range(len(b)): ind, ind2 = b[i] a[ind, ind2] = c[i] def vector_assign(a, b, c): a[b[:,0], b[:,1]] = c # 生成测试数据 a = np.ones([100,100]) b = np.random.randint(0, 100, size=(10000, 2)) c = np.random.rand(10000) print("循环赋值耗时:", timeit.timeit(lambda: loop_assign(a.copy(), b, c), number=100)) print("矢量化赋值耗时:", timeit.timeit(lambda: vector_assign(a.copy(), b, c), number=100))
运行结果通常是:循环耗时是矢量化的几十到上百倍。
内容的提问来源于stack exchange,提问作者Gaurav Singh
相关产品推荐
相关产品推荐

