Эффективное изменение формы разреженной матрицы, Python, SciPy 0.12

В другом сообщении об изменении размера разреженной матрицы в SciPy принятый ответ работает, когда необходимо добавить дополнительные строки или столбцы, используя scipy.sparse.vstack или hstack соответственно. В SciPy 0.12 ссылка reshape или set_shape по-прежнему не реализованы.

Существуют ли какие-либо устоявшиеся передовые методы изменения формы разреженной матрицы в SciPy 0.12? Было бы неплохо иметь некоторые сравнения времени.


person Saullo G. P. Castro    schedule 12.05.2013    source источник


Ответы (3)


Начиная с SciPy 1.1.0, reshape и set_shape методы реализованы для всех типов разреженных матриц. Подписи - это то, что вы ожидаете, и они настолько идентичны эквивалентным методам в NumPy, насколько это возможно (например, вы не можете изменить форму на вектор или тензор).

Подпись:

reshape(self, shape: Tuple[int, int], order: 'C'|'F' = 'C', copy: bool = False) -> spmatrix

Пример:

>>> from scipy.sparse import csr_matrix
>>> A = csr_matrix([[0,0,2,0], [0,1,0,3]])
>>> print(A)
  (0, 2)    2
  (1, 1)    1
  (1, 3)    3
>>> B = A.reshape((4,2))
>>> print(B)
  (1, 0)    2
  (2, 1)    1
  (3, 1)    3
>>> C = A.reshape((4,2), order='F')
>>> print(C)
  (0, 1)    2
  (3, 0)    1
  (3, 1)    3

Полное раскрытие: я написал реализации.

person drhagen    schedule 04.02.2019

Я не знаю каких-либо установленных хороших практик, поэтому вот довольно простая функция изменения формы для coo_matrix. Он преобразует свой аргумент в coo_matrix, поэтому он будет работать для других разреженных форматов (но возвращает coo_matrix).

from scipy.sparse import coo_matrix


def reshape(a, shape):
    """Reshape the sparse matrix `a`.

    Returns a coo_matrix with shape `shape`.
    """
    if not hasattr(shape, '__len__') or len(shape) != 2:
        raise ValueError('`shape` must be a sequence of two integers')

    c = a.tocoo()
    nrows, ncols = c.shape
    size = nrows * ncols

    new_size =  shape[0] * shape[1]
    if new_size != size:
        raise ValueError('total size of new array must be unchanged')

    flat_indices = ncols * c.row + c.col
    new_row, new_col = divmod(flat_indices, shape[1])

    b = coo_matrix((c.data, (new_row, new_col)), shape=shape)
    return b

Пример:

In [43]: a = coo_matrix([[0,10,0,0],[0,0,0,0],[0,20,30,40]])

In [44]: a.A
Out[44]: 
array([[ 0, 10,  0,  0],
       [ 0,  0,  0,  0],
       [ 0, 20, 30, 40]])

In [45]: b = reshape(a, (2,6))

In [46]: b.A
Out[46]: 
array([[ 0, 10,  0,  0,  0,  0],
       [ 0,  0,  0, 20, 30, 40]])

Теперь я уверен, что здесь есть несколько постоянных участников, которые могут придумать что-то лучше (быстрее, больше памяти, меньше заполнения... :)

person Warren Weckesser    schedule 13.05.2013
comment
Обновление: эта проблема была решена в ENH: изменение формы разреженных матриц #3957, @Warren Здесь было выбрано решение Weckesser. - person zaxliu; 18.09.2015

У меня есть один рабочий пример для матрицы CSR, но я не могу гарантировать, что он всегда работает

сглаживание матрицы A:

    indices = zeros_like(A.indices)
    indices[A.indptr[1:-1]] = A.shape[1]
    indices = cumsum( indices)+A.indices
    A_flat = sparse.csc_matrix((T_rot.data, indices,[0,size(A)]),shape=(prod(A.shape),1))

изменение матрицы A

    indices = zeros_like(A.indices)
    indices[A.indptr[1:-1]] = A.shape[1]
    indices = cumsum( indices)+A.indices

    indices %= N*A.shape[1]
    indptr = r_[0, where(diff(indices)<0)[0]+1, size(A)]
    A_reshaped = sparse.csc_matrix((A.data, indices,indptr),shape=(N*A.shape[1],A.shape[0]/N ))
person Tomas    schedule 03.07.2015