Как получить взгляды на разреженные матрицы? - PullRequest
0 голосов
/ 26 августа 2018

При разрезании массива numpy мы получаем представление о соответствующих данных. Однако, похоже, что это не так для разреженных матриц из scipy.sparse. Хотя в документах кратко упоминается нарезка для класса lil_matrix, неясно, как (или если) можно получить представления о данных.

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

import numpy as np
from scipy.sparse import lil_matrix


def test(matrix):
    print('\n=== Testing {} ==='.format(type(matrix)))

    a = matrix[:, 0]
    b = matrix[0, :]

    a[0] = 100
    M[0, 1] = 200
    M[1, 0] = 200
    print('a = '); print(a)
    print('b = '); print(b)


M = np.arange(4).reshape(2, 2) + 1
S = lil_matrix(M)

test(M)
test(S)

Какие выходы:

=== Testing <class 'numpy.ndarray'> ===
a = 
[100 200]
b = 
[100 200]

=== Testing <class 'scipy.sparse.lil.lil_matrix'> ===
a = 
  (0, 0)    100
  (1, 0)    3
b = 
  (0, 0)    1
  (0, 1)    2

Проверено на Python 3.6.6, numpy==1.14.5, scipy==1.1.0.

1 Ответ

0 голосов
/ 26 августа 2018

Я съем свои слова - частично. Существует метод lilmatrix getrowview (но не getcolview).

Матрица lil имеет 2 атрибута массива dtype объектов, data и rows. Оба содержат списки, по одному для каждой строки.

def getrow(self, i):
    """Returns a copy of the 'i'th row.
    """
    i = self._check_row_bounds(i)
    new = lil_matrix((1, self.shape[1]), dtype=self.dtype)
    new.rows[0] = self.rows[i][:]
    new.data[0] = self.data[i][:]
    return new

def getrowview(self, i):
    """Returns a view of the 'i'th row (without copying).
    """
    new = lil_matrix((1, self.shape[1]), dtype=self.dtype)
    new.rows[0] = self.rows[i]
    new.data[0] = self.data[i]
    return new

Небольшое тестирование показывает, что изменение элементов представления строки влияет на родительский элемент, и v.v.

Это view работает, потому что массив объектов содержит указатели. Как и в случае указателей в списке, ими можно поделиться. И если все сделано правильно, такой список можно изменить на месте.

Я нашел это, выполнив поиск по странице view в документации lil_matrix. Я не нахожу ничего похожего для других форматов.

В формате csr имеются числовые функции, которые работают напрямую с атрибутом .data. Это возможно, если вы не изменяете разреженность и хотите изменить только ненулевые значения. И это можно изменить на месте. В ограниченных случаях может быть возможно создать новую разреженную матрицу, которая разделяет фрагменты атрибута данных другого, но это не будет таким общим, как ndarray слайсинг.


In [88]: M = sparse.lil_matrix((4,10),dtype=int)
In [89]: M[0,1::2] = 1
In [90]: M[1,::2] = 2
In [91]: M1 = M.getrowview(0)

In [92]: M1[0,::2] = 3
In [94]: M.A
Out[94]: 
array([[3, 1, 3, 1, 3, 1, 3, 1, 3, 1],
       [2, 0, 2, 0, 2, 0, 2, 0, 2, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

In [95]: M[0,1::2] = 4
In [97]: M1.A
Out[97]: array([[3, 4, 3, 4, 3, 4, 3, 4, 3, 4]])

Следуя этой модели, я мог бы сделать 'advanced-index view, something that ndarray` не делает:

In [98]: M2 = sparse.lil_matrix((2,10), dtype=int)
In [99]: M2.rows[:] = M.rows[[0,3]]
In [100]: M2.data[:] = M.data[[0,3]]
In [101]: M2.A
Out[101]: 
array([[3, 4, 3, 4, 3, 4, 3, 4, 3, 4],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
In [102]: M2[:,::2] *= 10
In [103]: M2.A
Out[103]: 
array([[30,  4, 30,  4, 30,  4, 30,  4, 30,  4],
       [ 0,  0,  0,  0,  0,  0,  0,  0,  0,  0]])
In [104]: M1.A
Out[104]: array([[30,  4, 30,  4, 30,  4, 30,  4, 30,  4]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...