[英]Fast way for weighted counting of numpy arrays
我有两个形状相同的二维 numpy arrays:
idx = np.array([[1, 2, 5, 6],[1, 3, 5, 2]])
val = np.array([[0.1, 0.5, 0.3, 0.2], [0.1, 0., 0.8, 0.2]])
我知道我们可以使用np.bincount
设置val
作为权重:
np.bincount(idx.reshape(-1), weights=val.reshape(-1))
但这并不是我想要的。 np.bincount
将零放在索引不存在的地方。 在示例中,结果是:
array([0. , 0.2, 0.7, 0. , 0. , 1.1, 0.2])
但我不希望这些额外的零用于不存在的索引。 我希望加权计数对应于np.unique(idx)
array([1, 2, 3, 5, 6])
我的预期结果是:
array([0.2, 0.7, 0., 1.1, 0.2])
任何人都有一个想法来有效地做到这一点? 我的idx
和val
非常大,有超过 100 万个元素。
您可以有效地使用 numpy 库。
看一下这个:
output = []
for i in np.unique(idx):
wt = (idx == i)
if i == 0:
zeros = wt*(idx+1)
l = np.sum(zeros*val)
else:
zeros = wt*idx
l = np.sum(zeros*val)/i
output.append(l)
print(output)
这是相当快的。 我希望它有所帮助。
您可能知道,在 python 中使用 for 循环并不是提高效率的好主意:
您可以尝试使用 np.unique 方法对 bincount 的 output 进行索引:
>>> np.bincount(idx.reshape(-1), val.reshape(-1))[np.unique(idx)]
array([0.2, 0.7, 0. , 1.1, 0.2])
如果您只想摆脱零,这可能是最快的方法。
成功的关键在于:
执行此操作的代码(非常简洁且没有任何循环)是:
unq = np.unique(idx)
mapper = pd.Series(range(unq.size), index=unq)
np.bincount(mapper[idx.reshape(-1)], weights=val.reshape(-1))
对于您的样本数据,结果是:
array([0.2, 0.7, 0. , 1.1, 0.2])
方法一:
将np.unique
与return_inverse=True
一起使用。
idx = np.array([[1, 2, 5, 6],[1, 3, 5, 2]])
val = np.array([[0.1, 0.5, 0.3, 0.2], [0.1, 0., 0.8, 0.2]])
unq,inv=np.unique(idx,return_inverse=True)
np.bincount(inv,val.reshape(-1))
# array([0.2, 0.7, 0. , 1.1, 0.2])
方法二:
使用 bincount 然后删除(真正的)零。
np.bincount(idx.reshape(-1),val.reshape(-1))[np.bincount(idx.reshape(-1)).nonzero()]
# array([0.2, 0.7, 0. , 1.1, 0.2])
哪个更好将取决于idx
的分布情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.