Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python csr_矩阵的集合行_Python_Performance_Sparse Matrix - Fatal编程技术网

Python csr_矩阵的集合行

Python csr_矩阵的集合行,python,performance,sparse-matrix,Python,Performance,Sparse Matrix,我有一个稀疏的csr_矩阵,我想将一行的值更改为不同的值。然而,我找不到一个简单有效的实现。这就是它必须做的: A = csr_matrix([[0, 1, 0], [1, 0, 1], [0, 1, 0]]) new_row = np.array([-1, -1, -1]) print(set_row_csr(A, 2, new_row).todense()) >>> [[ 0, 1, 0], [

我有一个稀疏的csr_矩阵,我想将一行的值更改为不同的值。然而,我找不到一个简单有效的实现。这就是它必须做的:

A = csr_matrix([[0, 1, 0],
                [1, 0, 1],
                [0, 1, 0]])
new_row = np.array([-1, -1, -1])
print(set_row_csr(A, 2, new_row).todense())

>>> [[ 0,  1, 0],
     [ 1,  0, 1],
     [-1, -1, -1]]
这是我当前的
set\u row\u csr

def set_row_csr(A, row_idx, new_row):
    A[row_idx, :] = new_row
    return A

但这给了我一个
SparseEfficiencyWarning
。有没有办法不用手动索引杂耍来完成这项工作,或者这是我唯一的出路?

最后,我设法用索引杂耍来完成这项工作

def set_row_csr(A, row_idx, new_row):
    '''
    Replace a row in a CSR sparse matrix A.

    Parameters
    ----------
    A: csr_matrix
        Matrix to change
    row_idx: int
        index of the row to be changed
    new_row: np.array
        list of new values for the row of A

    Returns
    -------
    None (the matrix A is changed in place)

    Prerequisites
    -------------
    The row index shall be smaller than the number of rows in A
    The number of elements in new row must be equal to the number of columns in matrix A
    '''
    assert sparse.isspmatrix_csr(A), 'A shall be a csr_matrix'
    assert row_idx < A.shape[0], \
            'The row index ({0}) shall be smaller than the number of rows in A ({1})' \
            .format(row_idx, A.shape[0])
    try:
        N_elements_new_row = len(new_row)
    except TypeError:
        msg = 'Argument new_row shall be a list or numpy array, is now a {0}'\
        .format(type(new_row))
        raise AssertionError(msg)
    N_cols = A.shape[1]
    assert N_cols == N_elements_new_row, \
            'The number of elements in new row ({0}) must be equal to ' \
            'the number of columns in matrix A ({1})' \
            .format(N_elements_new_row, N_cols)

    idx_start_row = A.indptr[row_idx]
    idx_end_row = A.indptr[row_idx + 1]
    additional_nnz = N_cols - (idx_end_row - idx_start_row)

    A.data = np.r_[A.data[:idx_start_row], new_row, A.data[idx_end_row:]]
    A.indices = np.r_[A.indices[:idx_start_row], np.arange(N_cols), A.indices[idx_end_row:]]
    A.indptr = np.r_[A.indptr[:row_idx + 1], A.indptr[(row_idx + 1):] + additional_nnz]
def set_row_csr(A,row_idx,new_row):
'''
替换CSR稀疏矩阵a中的一行。
参数
----------
A:csr_矩阵
改变矩阵
行_idx:int
要更改的行的索引
新行:np.array
表的行的新值列表
退换商品
-------
无(矩阵A已更改到位)
先决条件
-------------
行索引应小于表中的行数
新行中的元素数必须等于矩阵A中的列数
'''
断言sparse.isspmatrix_csr(A),“A应为csr_矩阵”
断言行_idx
physicalattraction的答案确实要快得多。这比我的解决方案要快得多,我的解决方案是只添加一个单独的矩阵和一行集合。虽然添加溶液比切片溶液快

对我来说,在csr_矩阵中设置行或在csc_矩阵中设置列的最快方法是自己修改底层数据

def time_copy(A, num_tries = 10000):
    start = time.time()
    for i in range(num_tries):
        B = A.copy()
    end = time.time()
    return end - start

def test_method(func, A, row_idx, new_row, num_tries = 10000):
    start = time.time()
    for i in range(num_tries):
        func(A.copy(), row_idx, new_row)
    end = time.time()
    copy_time = time_copy(A, num_tries)
    print("Duration {}".format((end - start) - copy_time))

def set_row_csr_slice(A, row_idx, new_row):
    A[row_idx,:] = new_row

def set_row_csr_addition(A, row_idx, new_row):
    indptr = np.zeros(A.shape[1] + 1)
    indptr[row_idx +1:] = A.shape[1]
    indices = np.arange(A.shape[1])
    A += csr_matrix((new_row, indices, indptr), shape=A.shape)

>>> A = csr_matrix((np.ones(1000), (np.random.randint(0,1000,1000), np.random.randint(0, 1000, 1000))))
>>> test_method(set_row_csr_slice, A, 200, np.ones(A.shape[1]), num_tries = 10000)
Duration 4.938395977020264

>>> test_method(set_row_csr_addition, A, 200, np.ones(A.shape[1]), num_tries = 10000)
Duration 2.4161765575408936

>>> test_method(set_row_csr, A, 200, np.ones(A.shape[1]), num_tries = 10000)
Duration 0.8432261943817139
切片解也会随着矩阵的大小和稀疏性而变得更糟

# Larger matrix, same fraction sparsity
>>> A = csr_matrix((np.ones(10000), (np.random.randint(0,10000,10000), np.random.randint(0, 10000, 10000))))
>>> test_method(set_row_csr_slice, A, 200, np.ones(A.shape[1]), num_tries = 10000)
Duration 18.335174798965454

>>> test_method(set_row_csr, A, 200, np.ones(A.shape[1]), num_tries = 10000)
Duration 1.1089558601379395

# Super sparse matrix
>>> A = csr_matrix((np.ones(100), (np.random.randint(0,10000,100), np.random.randint(0, 10000, 100))))
>>> test_method(set_row_csr_slice, A, 200, np.ones(A.shape[1]), num_tries = 10000)
Duration 13.371600151062012

>>> test_method(set_row_csr, A, 200, np.ones(A.shape[1]), num_tries = 10000)
Duration 1.0454308986663818

设置行\u csr
有问题。是的,它很快,而且似乎对一些测试用例有效。然而,在我的测试用例中,它似乎破坏了csr稀疏矩阵的内部csr结构。稍后尝试
lil\u矩阵(A)
,您将看到错误消息。

在physicalattraction的回答中,
len(新行)
必须等于
A.shape[1]
添加稀疏行时可能不感兴趣的内容

因此,根据他的回答,我提出了一种方法,在csr中设置行,同时保留sparcity属性。此外,我还添加了一种将密集数组转换为稀疏数组的方法(在数据、索引格式上)

def到_稀疏(密集arr):
稀疏=[(数据,索引)用于索引,如果数据!=0,则枚举(密集)中的数据
#将元组列表转换为列表
稀疏=列表(映射(列表,zip(*稀疏)))
#返回数据和索引
返回稀疏[0],稀疏[1]
def set_row_csr_unbounded(A、row_idx、new_row_数据、new_row_索引):
'''
替换CSR稀疏矩阵a中的一行。
参数
----------
A:csr_矩阵
改变矩阵
行_idx:int
要更改的行的索引
新的行数据:np.array
表的行的新值列表
新的行索引:np.array
新行的索引列表
退换商品
-------
无(矩阵A已更改到位)
先决条件
-------------
行索引应小于表中的行数
行数据和行索引的大小必须相同
'''
断言isspmatrix_csr(A),“A应为csr_矩阵”
断言行_idx
这是我的方法:

A = A.tolil()
A[index, :] = new_row
A = A.tocsr()

只需转换为
lil_矩阵
,更改行并转换回。

您是否对其进行了时间测试?有了这些
np.r\u
调用,我想知道它是否能节省时间。老实说:如果我对它进行了时间测试,我就不记得了。现在已经两年了。我创建了一个非常小的测试矩阵,使用
set\u row\u csr
进行修改,并使用
lil\u矩阵(a)
进行转换。没有出现错误,但。。。
A = A.tolil()
A[index, :] = new_row
A = A.tocsr()