Python 稀疏矩阵中top k元素的增值

Python 稀疏矩阵中top k元素的增值,python,sorting,numpy,scipy,sparse-matrix,Python,Sorting,Numpy,Scipy,Sparse Matrix,我试图找到一种有效的方法,让我增加一个稀疏矩阵的前k值一些常量值。我目前正在使用以下代码,这对于非常大的矩阵来说非常缓慢: a = csr_matrix((2,2)) #just some sample data a[1,1] = 3. a[0,1] = 2. y = a.tocoo() idx = y.data.argsort()[::-1][:1] #k is 1 for i, j in izip(y.row[idx], y.col[idx]): a[i,j] += 1 实际上排

我试图找到一种有效的方法,让我增加一个稀疏矩阵的前k值一些常量值。我目前正在使用以下代码,这对于非常大的矩阵来说非常缓慢:

a = csr_matrix((2,2)) #just some sample data
a[1,1] = 3.
a[0,1] = 2.

y = a.tocoo()
idx = y.data.argsort()[::-1][:1] #k is 1
for i, j in izip(y.row[idx], y.col[idx]):
    a[i,j] += 1

实际上排序似乎很快,问题在于我的最后一个循环,我通过排序索引增加值。希望有人知道如何加快速度。

您可以直接修改
a.data
而不是迭代行/列索引和修改单个元素,从而大大加快速度:

idx = a.data.argsort()[::-1][:1] #k is 1
a.data[idx] += 1
这也节省了从CSR-->COO转换的时间

更新 正如@WarrenWeckesser正确指出的那样,由于您只对
k
最大元素的索引感兴趣,而不关心它们的顺序,因此可以使用
argpartition
而不是
argsort
。当
a.data
较大时,这可以快得多

例如:

from scipy import sparse

# a random sparse array with 1 million non-zero elements
a = sparse.rand(10000, 10000, density=0.01, format='csr')

# find the indices of the 100 largest non-zero elements
k = 100

# using argsort:
%timeit a.data.argsort()[-k:]
# 10 loops, best of 3: 135 ms per loop

# using argpartition:
%timeit a.data.argpartition(-k)[-k:]
# 100 loops, best of 3: 13 ms per loop

# test correctness:
np.all(a.data[a.data.argsort()[-k:]] == 
       np.sort(a.data[a.data.argpartition(-k)[-k:]]))
# True

通过直接修改
a.data
而不是迭代行/列索引和修改单个元素,您可能会大大加快速度:

idx = a.data.argsort()[::-1][:1] #k is 1
a.data[idx] += 1
这也节省了从CSR-->COO转换的时间

更新 正如@WarrenWeckesser正确指出的那样,由于您只对
k
最大元素的索引感兴趣,而不关心它们的顺序,因此可以使用
argpartition
而不是
argsort
。当
a.data
较大时,这可以快得多

例如:

from scipy import sparse

# a random sparse array with 1 million non-zero elements
a = sparse.rand(10000, 10000, density=0.01, format='csr')

# find the indices of the 100 largest non-zero elements
k = 100

# using argsort:
%timeit a.data.argsort()[-k:]
# 10 loops, best of 3: 135 ms per loop

# using argpartition:
%timeit a.data.argpartition(-k)[-k:]
# 100 loops, best of 3: 13 ms per loop

# test correctness:
np.all(a.data[a.data.argsort()[-k:]] == 
       np.sort(a.data[a.data.argpartition(-k)[-k:]]))
# True

干杯,干得不错!由于只需要
k
最大的元素,因此可以使用
arpartition
而不是
argsort
。如果
a.data
很大,这可能会显著提高性能。@WarrenWeckesser很好的建议-我用两个MethodScheer的一些基准更新了我的答案,这工作做得很好!由于只需要
k
最大的元素,因此可以使用
arpartition
而不是
argsort
。如果
a.data
很大,这可以显著提高性能。@WarrenWeckesser很好的建议-我用这两种方法的一些基准更新了我的答案