[英]Scipy find minimum nonzero element of a sparse matrix for each row
我試圖找到每行稀疏矩陣的最小元素的位置和值。 下面給出了該問題的一個玩具示例:這里,我們有一個 3x6 稀疏矩陣“M”。
H = np.array([[1, 2, 3, 0, 4, 0 ,0],
[0, 5, 0, 6, 0, 0 ,0],
[0, 0, 0, 7, 0, 0 ,8], dtype = np.float32)
M = scipy.sparse.csr_matrix(H)
然后,我想獲得的是每行的非零最小元素。 對於上面的例子:
min_elements = some_function(M,axis = 0)
並以min_elements = [1,5,7]
的形式接收回報。 方法M.min(axis=0)
不適用於我的情況,因為每行的最小元素為零,因此返回一個全零數組。
因此,是否有任何有效的方法可以使用稀疏矩陣以計算有效的方式實現這種功能。 在我的一般情況下,稀疏矩陣將非常龐大並且需要大量額外的計算。 因此,性能/速度是我的主要基准。
謝謝!
In [333]: from scipy import sparse
In [334]: M = sparse.csr_matrix(H)
In [335]: M
Out[335]:
<3x7 sparse matrix of type '<class 'numpy.float32'>'
with 8 stored elements in Compressed Sparse Row format>
M
存儲為:
In [336]: M.indptr
Out[336]: array([0, 4, 6, 8], dtype=int32)
In [337]: M.data
Out[337]: array([1., 2., 3., 4., 5., 6., 7., 8.], dtype=float32)
In [338]: M.indices
Out[338]: array([0, 1, 2, 4, 1, 3, 3, 6], dtype=int32)
我們可以迭代indptr
定義的切片,並取最小值:
In [340]: for i in range(M.shape[0]):
...: sl = slice(M.indptr[i],M.indptr[i+1])
...: x, y = M.data[sl], M.indices[sl]
...: m = np.argmin(x)
...: print(y[m], x[m])
...:
0 1.0
1 5.0
3 7.0
這可以簡化一點,但它給出了基本的想法。
以lil
格式描繪發生的事情可能更容易:
In [341]: Ml = M.tolil()
In [342]: Ml.data
Out[342]:
array([list([1.0, 2.0, 3.0, 4.0]), list([5.0, 6.0]), list([7.0, 8.0])],
dtype=object)
In [343]: Ml.rows
Out[343]: array([list([0, 1, 2, 4]), list([1, 3]), list([3, 6])], dtype=object)
In [344]: for d,r in zip(Ml.data, Ml.rows):
...: m = np.argmin(d)
...: print(r[m], d[m])
...:
0 1.0
1 5.0
3 7.0
以前的 SO 要求按行提供最小(或最大)N 值之類的東西。
稀疏最適合可以表示為某種矩陣乘法的事物。 這包括行(或列)總和。 甚至csr
索引也是通過矩陣乘法完成的。 其他逐行操作並不那么容易。
您可以翻轉所有數據並找到最大值。 這是假設您的所有數據都是正數,如示例中所示。
M_inv = M.copy()
M_inv.data = 1/M.data
one_over_min_M = M_inv.max(axis=1)
min_M = 1/one_over_min_M.to_array()
在你的例子中,我得到了輸出
[[1. ]
[5. ]
[6.9999995]]
那里有一些可怕的數字錯誤,但如果你願意round
你的答案......
編輯:如果您追求索引並想做M_inv.argmax(axis=1)
,這種方法可能會被贖回,否則它可能不是最好的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.