Numpy:填充共现矩阵的最快方法

时间:2020-02-29 22:28:50

标签: python numpy

我有一长串的索引元组(很多重复项),以及一个n×n索引的矩阵。每个元组都表示同时出现。

例如:

a = np.zeros(shape=(indexCount,indexCount))

我已经尝试过了:

for i1,i2 in coocPairs:  #for instance (2374, 22003)
   a[i1][i2}+=1  #takes way too long

或:

np.put(a,coocPairs,1) #which obviously does not increment

或:

np.add(a,coocPairs,1) #which takes even longer.

在理想的世界中,会有一个函数接受我的元组列表,并用它建立一个共现矩阵,但是可惜(文档不是很有帮助)。我认为解决方案可能更多地在代码的python方面,但是我没有想法。任何帮助欢迎。谢谢您的宝贵时间,

2 个答案:

答案 0 :(得分:1)

您可以使用np.add.at

np.add.at(a,tuple(coocPairs.T),1)

如果速度不够快,则可以使用更快但基于np.bincount的简单解决方案。那些依赖于使用np.ravel_multi_index的平坦索引。

答案 1 :(得分:1)

您可以使用collections.Counter来获取将实际出现在矩阵中的值。这是可行的,因为元组是可哈希的。分配变得非常简单:

counts = collections.Counter(coocPairs)
ind = np.array(list(counts.keys())).T
a[ind[0], ind[1]] = list(counts.values())

通常,np.uniquereturn_counts=TrueCounter的替身。在这种情况下,必须指定轴,并记住这将是较慢的解决方案之一:

ind, count = np.unique(coocPairs, return_counts=True, axis=0)
a[ind.T[0], ind.T[1]] = count

相反,您可以将对转换为raved矩阵中的线性索引:

ind = np.ravel_multi_index(tuple(np.array(coocPairs).T), a.shape)

现在您可以做

ind, count = np.unique(ind, return_counts=True)
a.ravel()[ind] = count

或者,您可以使用np.bincount更快地获得计数,或者使用np.add.at来避免进行前期计数。索引混乱的bincount解决方案为您节省了预先分配a的麻烦:

ind = np.ravel_multi_index(tuple(np.array(coocPairs).T), (n, n))
a = np.bincount(ind, minlength=n * n).reahape(n, n)
相关问题