Python 如何测试两个稀疏数组是否(几乎)相等?

Python 如何测试两个稀疏数组是否(几乎)相等?,python,numpy,scipy,sparse-matrix,Python,Numpy,Scipy,Sparse Matrix,我想检查两个稀疏数组是否(几乎)相等。而对于numpy阵列,您可以执行以下操作: import numpy as np a = np.ones(200) np.testing.assert_array_almost_equal(a, a) 这不适用于稀疏数组,我可以理解(对于较小的矩阵或与数组大小相关的错误,返回errorAttributeError:ravel not found)。是否有一个scipy等价物来测试稀疏矩阵?我可以将稀疏矩阵转换为密集矩阵,并使用numpy测试函数,但有时由

我想检查两个稀疏数组是否(几乎)相等。而对于numpy阵列,您可以执行以下操作:

import numpy as np

a = np.ones(200)
np.testing.assert_array_almost_equal(a, a)
这不适用于稀疏数组,我可以理解(对于较小的矩阵或与数组大小相关的错误,返回error
AttributeError:ravel not found
)。是否有一个scipy等价物来测试稀疏矩阵?我可以将稀疏矩阵转换为密集矩阵,并使用numpy测试函数,但有时由于(内存/大小)限制,这是不可能的。例如:

from scipy import sparse

b = sparse.rand(80000,8000,density=0.01)
type(b)  # <class 'scipy.sparse.coo.coo_matrix'>
c = b.toarray()  # ValueError: array is too big; `arr.size * arr.dtype.itemsize` is larger than the maximum possible size.
从scipy导入稀疏
b=稀疏.rand(8000000,密度=0.01)
(b)类#
c=b.toarray()#值错误:数组太大`arr.size*arr.dtype.itemsize`大于最大可能大小。

是否可以测试这些较大的scipy数组是否相等,或者我是否应该测试较小的样本?

假设我们不关心该数组中可能在公差值范围内的非零,我们只需获得行、列索引和相应的值,并查找索引之间的精确匹配,而
allclose()

因此,实施将是必要的-

from scipy.sparse import find

def allclose(A, B, atol = 1e-8):

    # If you want to check matrix shapes as well
    if np.array_equal(A.shape, B.shape)==0:
        return False

    r1,c1,v1 = find(A)
    r2,c2,v2 = find(B)
    index_match = np.array_equal(r1,r2) & np.array_equal(c1,c2)

    if index_match==0:
        return False
    else:  
        return np.allclose(v1,v2, atol=atol)
下面是另一个使用
非零
数据
方法替换
查找
函数的方法-

def allclose_v2(A, B, atol = 1e-8):
    # If you want to check matrix shapes as well
    if np.array_equal(A.shape, B.shape)==0:
        return False

    r1,c1 = A.nonzero()
    r2,c2 = B.nonzero()

    lidx1 = np.ravel_multi_index((r1,c1), A.shape)
    lidx2 = np.ravel_multi_index((r2,c2), B.shape)

    sidx1 = lidx1.argsort()
    sidx2 = lidx2.argsort()

    index_match = np.array_equal(lidx1[sidx1], lidx2[sidx2])
    if index_match==0:
        return False
    else:  
        v1 = A.data
        v2 = B.data        
        V1 = v1[sidx1]
        V2 = v2[sidx2]        
        return np.allclose(V1,V2, atol=atol)

我们可以在几个地方短路以进一步加速。在性能方面,我更关注的是只有值不同的情况。

可能希望将
np.allclose
放在
后面,如果索引匹配:
。如果
v1
v2
的长度不同,则会抛出错误。如果我理解正确,您建议比较行和列索引是否相同以及值是否接近。我喜欢这个想法,但是如果你不知道find()在你的例子中是如何工作的(如果我尝试使用它,它会抛出一个错误)。它是否与直接在比较语句中使用
A.row
A.col
A.data
相同?@BartDur猜测需要一个IF来比较长度是否相等。编辑好了。@DanielF谢谢。需要改进,等等。。。您正在使用的
find()
是?我一开始并不清楚,但现在一切都讲得通了,谢谢!