Подтвердить что ты не робот

Расширение (добавление строки или столбца) матрица scipy.sparse

Предположим, что у меня есть матрица NxN M (lil_matrix или csr_matrix) из scipy.sparse, и я хочу сделать ее (N + 1) xN, где M_modified [i, j] = M [i, j] для 0 <= я < N (и все j) и M [N, j] = 0 для всех j. В принципе, я хочу добавить строку нулей в нижнюю часть M и сохранить оставшуюся часть матрицы. Есть ли способ сделать это без копирования данных?

4b9b3361

Ответ 1

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

Обновить с дополнительной информацией:

LIL действительно поддерживает LInked List, но текущая реализация не совсем соответствует названию. Массивы Numpy, используемые для data и rows, являются объектами типа. Каждый из объектов в этих массивах - это фактически списки Python (пустой список, когда все значения равны нулю в строке). Списки Python не являются точно связанными списками, но они являются близкими и, откровенно говоря, лучшим выбором из-за O (1) поиска. Лично я не сразу вижу смысл использовать массив объектов Numpy здесь, а не просто список Python. Вы могли бы довольно легко изменить текущую реализацию lil, чтобы вместо этого использовать списки Python, что позволит вам добавить строку без копирования всей матрицы.

Ответ 2

У Scipy нет способа сделать это без копирования данных, но вы можете сделать это самостоятельно, изменив атрибуты, которые определяют разреженную матрицу.

Есть 4 атрибута, которые составляют csr_matrix:

: массив, содержащий фактические значения в матрице

индексы: массив, содержащий индекс столбца, соответствующий каждому значению в данных

indptr: массив, который указывает индекс перед первым значением в данных для каждой строки. Если строка пуста, то индекс совпадает с предыдущим столбцом.

shape: Кортеж, содержащий форму матрицы

Если вы просто добавляете строку нулей в нижнюю часть, вам нужно изменить форму и indptr для вашей матрицы.

x = np.ones((3,5))
x = csr_matrix(x)
x.toarray()
>> array([[ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.],
          [ 1.,  1.,  1.,  1.,  1.]])
# reshape is not implemented for csr_matrix but you can cheat and do it  yourself.
x._shape = (4,5)
# Update indptr to let it know we added a row with nothing in it. So just append the last
# value in indptr to the end.
# note that you are still copying the indptr array
x.indptr = np.hstack((x.indptr,x.indptr[-1]))
x.toarray()
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 0.,  0.,  0.,  0.,  0.]])

Вот функция для обработки более общего случая vstacking любых 2 csr_matrices. Вы все еще копируете базовые массивы numpy, но все же значительно быстрее, чем метод scipy vstack.

def csr_vappend(a,b):
    """ Takes in 2 csr_matrices and appends the second one to the bottom of the first one. 
    Much faster than scipy.sparse.vstack but assumes the type to be csr and overwrites
    the first matrix instead of copying it. The data, indices, and indptr still get copied."""

    a.data = np.hstack((a.data,b.data))
    a.indices = np.hstack((a.indices,b.indices))
    a.indptr = np.hstack((a.indptr,(b.indptr + a.nnz)[1:]))
    a._shape = (a.shape[0]+b.shape[0],b.shape[1])
    return a

Ответ 3

Не уверен, что вы все еще ищете решение, но, возможно, другие могут заглянуть в hstack и vstack - http://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.hstack.html. Я думаю, мы можем определить csr_matrix для одной дополнительной строки, а затем vstack с предыдущей матрицей.