原文链接
稀疏矩阵如下
import numpy as np
from scipy.sparse import
x = csr_matrix(np.array([[1, 0, 2, 0, 3],
[0, 4, 0, 5, 0]]))
当需要将对其元素小于3的元素修改为0时,很容易想到这种方式
x[x < 3] = 0
但是这种方式在大型稀疏矩阵的情况下会报以下的警告
/home/miniconda3/lib/python3.6/site-packages/scipy/sparse/compressed.py:282: SparseEfficiencyWarning: Comparing a sparse matrix with a scalar greater than zero using < is inefficient, try using >= instead.
warn(bad_scalar_msg, SparseEfficiencyWarning)
因为大型稀疏矩阵的情况下,大多数元素都为0,在用<
号判断时,很多为0的元素也需要重新赋值,所以这种方式极其不好,可以看到warning中说到>=
的判断要更有效率。
那么,我们可以这样来选取,不是所有小于3的元素都置为0,而是在所有非0元素中将小于3的置为0
nonzero_mask = np.array(x[x.nonzero()] < 3)[0]
然后就可以获取相应的行列
rows = x.nonzero()[0][nonzero_mask]
cols = x.nonzero()[1][nonzero_mask]
x[rows, cols] = 0
print(x.todense())
# 最后消除掉0
x.eliminate_zeros() # This happens inplace
[[0 0 0 0 3]
[0 4 0 5 0]]
在开发的过程中,经常涉及修改稀疏矩阵的值的操作,之前经常是直接通过csr_matrix
的属性遍历修改,需要自己遍历实现修改data里面的内容
import numpy as np
from scipy.sparse import csr_matrix
x = csr_matrix(np.array([[1, 0, 2, 0, 3],
[0, 4, 0, 5, 0]]))
print(x)
print(x.toarray())
row, col = x.shape
# 当data[i][j] < 3时设置为0
for i in range(row):
for r in range(x.indptr[i], x.indptr[i+1]):
if x.data[r] < 3:
x.data[r] = 0
print(x.toarray())
输出结果如下, 如果对csr_matrix中的indptr和data属性不清楚,可以参考稀疏矩阵的存储方式
1---
(0, 0) 1
(0, 2) 2
(0, 4) 3
(1, 1) 4
(1, 3) 5
2---
[[1 0 2 0 3]
[0 4 0 5 0]]
3---
[[0 0 0 0 3]
[0 4 0 5 0]]