как сохранить только сжатые разреженные индексы строк, которые находятся в списке

#python #sparse-matrix

#питон #разреженная матрица

Вопрос:

допустим, у меня есть матрица смежности в формате csr:

 row = np.array([0, 0, 1, 3, 2, 2,3,4,4]) col = np.array([0, 4, 2, 2, 3, 1,4,0,3]) data = np.array([1]*len(row)) X= sp.csr_matrix((data, (row, col)), shape=(5, 5))  print(X)  (0, 0) 1  (0, 4) 1  (1, 2) 1  (2, 1) 1  (2, 3) 1  (3, 2) 1  (3, 4) 1  (4, 0) 1  (4, 3) 1  print(X.todense()) [[1 0 0 0 1]  [0 0 1 0 0]  [0 1 0 1 0]  [0 0 1 0 1]  [1 0 0 1 0]]  

у меня есть список узлов, которые я хочу сохранить, скажем, узлы 1 и 2 keep = [1,2] как бы я сохранил все индексы в X, которые находятся в списке «сохранить» ? Например, я хочу, чтобы в конечном итоге все индексы, строка или столбец которых есть в списке, сохранялись:

 (1, 2) 1  (2, 1) 1  (2, 3) 1  (3, 2) 1  

X[keep] возвращает только строки 1,2:

 print(X[keep].todense()) [[0 0 1 0 0]  [0 1 0 1 0]]  

но я вижу, что узел 2 взаимодействует с узлами 1 и узлами 3; поэтому я хочу вернуть матрицу смежности, которая отражает двунаправленные связи матрицы смежности подмножества:

 [[0 0 1 0 0]  [0 1 0 1 0]  [0 0 1 0 0*]  

0* представляет собой тот факт, что, поскольку меня интересует только узел 1 (взаимодействует только с узлом 2) и узел 2 (взаимодействует с узлами 1 и 3), то, несмотря на то, что в исходной матрице мы наблюдаем, что узел 3 взаимодействует с узлами 2 и 4, узел 4 не в списке, поэтому мы его игнорируем. Следовательно, я хочу в конечном итоге получить что-то вроде:

 (1, 2) 1  (2, 1) 1  (2, 3) 1  (3, 2) 1  

…Я понимаю, что после внесения изменений в этот вопрос, чтобы попытаться прояснить, что я пытаюсь сделать, это может быть не такое простое решение, но я все еще не уверен, как к нему подойти.

Ответ №1:

Ваши индексы хранятся в:

 ix = X.nonzero()  

Вы можете создать логическое значение для подмножества ваших индексов:

 inkeep = np.isin(ix[0],keep) | np.isin(ix[1],keep)  

Тогда получите что-то вроде этого:

 np.array(ix)[:,inkeep].T  array([[1, 2],  [2, 1],  [2, 3],  [3, 2]], dtype=int32)  

Однако, если вы хотите вернуть разреженную матрицу, содержащую пересечение того, что вы хотите, т. Е. строк 1,2 и столбцов 1,2, это будет что-то вроде:

 X[1:3,1:3]  

или:

 X[keep,:][:,keep]  

Комментарии:

1. как бы я сохранил его в виде разреженной матрицы csr? после этого я понял, что мой mwe не совсем точно отражает то, с чем я работаю, но, по сути, я пытаюсь получить подмножество исходной симметричной/двунаправленной матрицы смежности. итак, исходя из моей первоначальной смежности, я выбираю только несколько узлов; и в подмножестве я хочу, чтобы оно все еще было симметричным … если это имеет смысл?

2. к сожалению, это не так. итак, если вы уже знаете нужные строки, разве это не вопрос подстановки матрицы в соответствии с этим?

3. хм, я думаю, что меня смущает разреженная матрица.. обычно я с ними не работаю, но мой набор данных большой, поэтому мне дали мой набор данных в виде сжатого csr. я знаю строки, которые пытаюсь сохранить, поэтому я попробовал X[сохранить], но он не возвращает симметричную матрицу

4. просто хотел прокомментировать, что я отредактировал свой оригинальный пост, чтобы лучше представить симметричную разреженную матрицу. ваш ответ действительно отражает то, что я опубликовал, а именно « строка = np.массив([0, 0, 1, 2, 2, 2,3,3,4,5,6,6,7,7,8,8,8,9]) col = np.массив([0, 4, 3, 2, 3, 1,1,4,2,3,1,4,3,2,2,3,1,4]) данные = np.массив([1]*len(строка)) X= sp.csr_matrix((данные, (строка, столбец)), форма=(10, 5))«

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

Ответ №2:

Я не пытался понять, что вы пытаетесь сделать. Но некоторые сведения о разреженных матрицах могут быть в порядке.

Сначала из ваших данных давайте создадим coo формат:

 In [1]: from scipy import sparse as sp In [2]: row = np.array([0, 0, 1, 3, 2, 2,3,4,4])  ...: col = np.array([0, 4, 2, 2, 3, 1,4,0,3])  ...: data = np.array([1]*len(row))  ...: X= sp.coo_matrix((data, (row, col)), shape=(5, 5))  ...:  In [3]: X Out[3]:  lt;5x5 sparse matrix of type 'lt;class 'numpy.int64'gt;'  with 9 stored elements in COOrdinate formatgt; In [4]: X.A Out[4]:  array([[1, 0, 0, 0, 1],  [0, 0, 1, 0, 0],  [0, 1, 0, 1, 0],  [0, 0, 1, 0, 1],  [1, 0, 0, 1, 0]]) In [5]: X.row,X.col Out[5]:  (array([0, 0, 1, 3, 2, 2, 3, 4, 4], dtype=int32),  array([0, 4, 2, 2, 3, 1, 4, 0, 3], dtype=int32))  

В coo , row,col,data атрибуты похожи на то, что вы указали, на самом деле они могут быть теми же массивами (если не копией).

csr Формат обрабатывается — сортируется и суммируется, если есть дубликаты. Строка/столбец были изменены, поэтому расположение не является очевидным.

 In [6]: Xr = X.tocsr() In [7]: Xr.indptr Out[7]: array([0, 2, 3, 5, 7, 9], dtype=int32) In [8]: Xr.indices Out[8]: array([0, 4, 2, 1, 3, 2, 4, 0, 3], dtype=int32)  

csr реализует большую часть скудной математики. Он также реализует индексирование; coo не реализует индексирование. На самом деле в более общих случаях csr индексация реализуется с помощью матричного умножения. Разреженные матрицы первоначально были разработаны для больших задач линейной алгебры, таких как конечно-разностный и конечно-элементный код. Я ничего с этим не делал scipy.sparse.csgraph .

Там, где это возможно csr , индексация пытается вести себя как соответствующая плотная индексация

 In [9]: keep=[1,2] In [10]: Xr[keep] Out[10]:  lt;2x5 sparse matrix of type 'lt;class 'numpy.int64'gt;'  with 3 stored elements in Compressed Sparse Row formatgt; In [11]: Xr.A[keep] Out[11]:  array([[0, 0, 1, 0, 0],  [0, 1, 0, 1, 0]])  

Это просто выбирает две строки из матрицы/массива.

nonzero Метод X (или Xr ) должен давать те же массивы, которые вы получаете из плотного массива. Опять же, это, по сути row/col , атрибуты coo .

 In [14]: X.nonzero() Out[14]:  (array([0, 0, 1, 3, 2, 2, 3, 4, 4], dtype=int32),  array([0, 4, 2, 2, 3, 1, 4, 0, 3], dtype=int32)) In [15]: np.nonzero(X.A) Out[15]: (array([0, 0, 1, 2, 2, 3, 3, 4, 4]), array([0, 4, 2, 1, 3, 2, 4, 0, 3]))  

Было бы лучше выяснить, что вы делаете с обычным массивом numpy, например X.A . Как только это сработает, вы сможете напрямую работать с разреженными матрицами и их атрибутами.