Создайте разреженную матрицу из списка кортежей, имеющих индексы столбца, где 1

#python #numpy #scipy #sparse-matrix #one-hot-encoding

Вопрос:

Проблема:

У меня есть список кортежей, каждый из которых представляет столбец 2D-массива, и каждый элемент кортежа представляет индекс этого столбца массива, равный 1; другие записи, которые не входят в этот кортеж, равны 0.

Я хочу создать разреженную матрицу с этим списком кортежей эффективным способом (стараясь не использовать для циклов).

Пример:

 # init values
list_tuples = [
 (0, 2, 4),
 (0, 2, 3),
 (1, 3, 4)
]

n = length(list_tuples)   1
m = 5 # arbritrary, however n >= max([ei for ei in list_tuples])   1

# what I need is a function which accepts this tuples and give the shape of the array
# (at least the row size, because the column size can be infered from the list of tuples)
A = some_function(list_tuples, array_shape = (m, n))

 

Тогда то, что я ожидаю получить, — это массив формы:

 [   
 [1, 1, 0]
 [0, 0, 1]  
 [1, 1, 0]
 [0, 1, 1]
 [1, 0, 1]
]
 

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

1. Наиболее эффективный способ создать разреженную матрицу — создать 3 массива, которые sparse.coo_matrix ожидают-строка, столбец и данные. Прочитайте документы и примеры.

Ответ №1:

Ваши значения являются теми indices , которые требуются для сжатого разреженного формата столбцов. Вам также понадобится indptr массив, который для ваших данных представляет собой совокупную сумму длин кортежей (перед 0). data Массив будет представлять собой массив единиц той же длины, что и сумма длин кортежей, которую вы можете получить из последнего элемента совокупной суммы. Вот как это выглядит с вашим примером:

 In [45]: from scipy.sparse import csc_matrix

In [46]: list_tuples = [
    ...:  (0, 2, 4),
    ...:  (0, 2, 3),
    ...:  (1, 3, 4)
    ...: ]

In [47]: indices = sum(list_tuples, ())  # Flatten the tuples into one sequence.

In [48]: indptr = np.cumsum([0]   [len(t) for t in list_tuples])

In [49]: a = csc_matrix((np.ones(indptr[-1], dtype=int), indices, indptr))

In [50]: a
Out[50]: 
<5x3 sparse matrix of type '<class 'numpy.int64'>'
    with 9 stored elements in Compressed Sparse Column format>

In [51]: a.A
Out[51]: 
array([[1, 1, 0],
       [0, 0, 1],
       [1, 1, 0],
       [0, 1, 1],
       [1, 0, 1]])
 

Обратите внимание, что csc_matrix выведено количество строк из максимума, найденного в индексах. Вы можете использовать shape параметр для переопределения этого, например

 In [52]: b = csc_matrix((np.ones(indptr[-1], dtype=int), indices, indptr), shape=(7, len(list_tuples)))

In [53]: b
Out[53]: 
<7x3 sparse matrix of type '<class 'numpy.int64'>'
    with 9 stored elements in Compressed Sparse Column format>

In [54]: b.A
Out[54]: 
array([[1, 1, 0],
       [0, 0, 1],
       [1, 1, 0],
       [0, 1, 1],
       [1, 0, 1],
       [0, 0, 0],
       [0, 0, 0]])
 

Вы также можете coo_matrix довольно легко сгенерировать. Сглаженный list_tuples дает индексы строк и np.repeat может быть использован для создания индексов столбцов:

 In [63]: from scipy.sparse import coo_matrix

In [64]: i = sum(list_tuples, ())  # row indices

In [65]: j = np.repeat(range(len(list_tuples)), [len(t) for t in list_tuples])

In [66]: c = coo_matrix((np.ones(len(i), dtype=int), (i, j)))

In [67]: c
Out[67]: 
<5x3 sparse matrix of type '<class 'numpy.int64'>'
    with 9 stored elements in COOrdinate format>

In [68]: c.A
Out[68]: 
array([[1, 1, 0],
       [0, 0, 1],
       [1, 1, 0],
       [0, 1, 1],
       [1, 0, 1]])