In [183]: arr = np.array([[0, 0, 1, 0, 1],
...: [1, 0, 0, 1, 0],
...: [0, 1, 1, 0, 0],
...: [1, 0, 0, 1, 0],
...: [0, 1, 0, 0, 0],
...: ])
...:
In [184]: from scipy import sparse
In [185]: M = sparse.lil_matrix(arr)
In [186]: M.rows
Out[186]:
array([list([2, 4]), list([0, 3]), list([1, 2]), list([0, 3]), list([1])],
dtype=object)
Это та же информация, что и из плотного массива:
In [187]: [np.where(row)[0] for row in arr]
Out[187]: [array([2, 4]), array([0, 3]), array([1, 2]), array([0, 3]), array([1])]
Полагаю, вы уже выяснили, как сгенерировать желаемый left
(или right
) из плотного массива, поэтому я не буду вдаваться в эти детали (мне лень разбираться с вашими спецификациями упаковки) ).
Для столбцов:
In [189]: M.T.rows
Out[189]:
array([list([1, 3]), list([2, 4]), list([0, 2]), list([1, 3]), list([0])],
dtype=object)
Из формата csc
вы можете использовать:
In [190]: Mc = sparse.csc_matrix(arr)
In [191]: Mc.indptr
Out[191]: array([0, 2, 4, 6, 8, 9], dtype=int32)
In [192]: Mc.indices
Out[192]: array([1, 3, 2, 4, 0, 2, 1, 3, 0], dtype=int32)
In [193]: for i in range(5):
...: print(Mc.indices[Mc.indptr[i]:Mc.indptr[i+1]])
...:
[1 3]
[2 4]
[0 2]
[1 3]
[0]
В этом примере все строки или столбцы имеют только 1 или 2 ненулевых значения. Я предполагаю, что в более широком, более общем, будет много ненулевых. Также с csc
(и csr
есть вероятность того, что индексы для каждой строки не сортируются - есть редкий метод для решения этой проблемы.
Что касается построения разреженной матрицы возврата, вы можете изменить атрибут data
копии (он будет иметь такую же разреженность).
In [194]: M.data
Out[194]:
array([list([1, 1]), list([1, 1]), list([1, 1]), list([1, 1]), list([1])],
dtype=object)
In [195]: Mc.data
Out[195]: array([1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=int64)
Или создать разреженную матрицу из массивов (как обычно для ввода в стиле coo
).
С моей lil
версией tch's
решение немного быстрее:
ind = sparse.lil_matrix(M.shape,dtype='int')
for i,row in enumerate(M.rows):
k = np.array(row)
ind[i,k] = np.roll(k+1,1)
Еще лучше с моей идеей заменить data
:
ind = M.copy()
for row,dat in zip(ind.rows,ind.data):
k = np.array(row)
dat[:] = np.roll(k+1,1).tolist()
или с Mr = Mc.tocsr()
ind = Mr.copy()
for i in range(Mr.shape[0]):
slc = slice(Mr.indptr[i],Mr.indptr[i+1])
k = Mr.indices[slc]
ind.data[slc] = np.roll(k+1,1)