[英]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.