You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于索引转换字典的Numpy广播优化:寻求替代循环的向量化实现方案

当然可以用向量化操作来替代for循环,这在处理大规模稀疏数组时能大幅提升效率!下面我会给出两种高效的实现方案,完全贴合你的需求:

方案一:基于有效行的映射拼接(适合稀疏场景)

这个方案针对arr1稀疏的特点,只处理非NaN的行,避免不必要的计算:

import numpy as np

# 你的原始数据
d = {0:[0,1,3], 1:[4,5,6], 2:[2,7,8], 3:[9]}
arr1 = np.array([[0,1], [np.NaN,np.NaN], [np.NaN,6.5], [16,0.2]])

# 1. 筛选arr1中不全为NaN的有效行索引
valid_indices = np.where(~np.isnan(arr1).all(axis=1))[0]

# 2. 构建arr2的目标索引数组:把每个有效索引对应的d中的列表拼接起来
target_indices = np.concatenate([d[idx] for idx in valid_indices])

# 3. 把arr1的有效行重复对应次数(和d中列表长度匹配)
repeat_counts = [len(d[idx]) for idx in valid_indices]
arr1_valid_repeated = np.repeat(arr1[valid_indices], repeat_counts, axis=0)

# 4. 初始化arr2并赋值
arr2_shape = (sum(len(v) for v in d.values()), arr1.shape[1])
arr2 = np.full(arr2_shape, np.nan)
arr2[target_indices] = arr1_valid_repeated

逻辑验证

运行这段代码后,arr2的结果和你原循环的输出完全一致:

  • 索引0、1、3的行是[0,1]
  • 索引2、7、8的行是[np.NaN,6.5]
  • 索引9的行是[16,0.2]
  • 其余行保持默认的np.NaN

方案二:全局映射数组赋值(适合字典键数量少的场景)

如果字典d的键数量不多(比如你的场景是600个),可以先构建一个从arr2索引到arr1索引的映射数组,再批量赋值:

import numpy as np

# 你的原始数据
d = {0:[0,1,3], 1:[4,5,6], 2:[2,7,8], 3:[9]}
arr1 = np.array([[0,1], [np.NaN,np.NaN], [np.NaN,6.5], [16,0.2]])

# 1. 构建映射数组:map_arr[i]表示arr2的第i行对应arr1的第map_arr[i]行
arr2_len = sum(len(v) for v in d.values())
map_arr = np.full(arr2_len, -1)  # 用-1标记无对应关系的位置
for idx, target_list in d.items():
    map_arr[target_list] = idx

# 2. 批量赋值:直接用映射数组索引arr1
arr2 = arr1[map_arr]

# 3. 处理arr1中原本为NaN的行对应的位置
nan_row_mask = np.isnan(arr1).all(axis=1)[map_arr]
arr2[nan_row_mask] = np.nan

为什么这两种方案更快?

你的原for循环是Python级别的迭代,每次循环都要处理一行数据,在arr2规模达到19万行时,效率会很低。而上面的方案用的是numpy的向量化操作,这些操作是基于C语言底层实现的,能充分利用CPU的并行计算能力,处理大规模数据时速度会提升数倍甚至数十倍。

对于你的场景(arr1是600行稀疏数组,arr2是19万行),方案一的效率会更高,因为它只处理arr1中的有效行,避免了对全NaN行的无用处理。

内容的提问来源于stack exchange,提问作者witherscp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:37:37