У Сципи нет способа сделать это без копирования данных, но вы можете сделать это самостоятельно, изменив атрибуты, определяющие разреженную матрицу.
Существует 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