我有一长串的索引元组(很多重复项),以及一个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方面,但是我没有想法。任何帮助欢迎。谢谢您的宝贵时间,
答案 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.unique
和return_counts=True
是Counter
的替身。在这种情况下,必须指定轴,并记住这将是较慢的解决方案之一:
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)