Как эффективно загрузить разреженную матрицу? - PullRequest
0 голосов
/ 28 декабря 2018

Имеется файл с такой структурой:

  • Однострочные строки являются ключами
  • Ненулевые значения ключей

Например:

abc
ef 0.85
kl 0.21
xyz 0.923
cldex 
plax 0.123
lion -0.831

Как создать разреженную матрицу, csr_matrix?

('abc', 'ef') 0.85
('abc', 'kl') 0.21
('abc', 'xyz') 0.923
('cldex', 'plax') 0.123
('cldex', 'lion') -0.31

Я пробовал:

from collections import defaultdict

x = """abc
ef  0.85
kl  0.21
xyz 0.923
cldex 
plax    0.123
lion    -0.831""".split('\n')

k1 = ''
arr = defaultdict(dict)
for line in x:
    line = line.strip().split('\t')
    if len(line) == 1:
        k1 = line[0]
    else:
        k2, v = line
        v = float(v)
        arr[k1][k2] = v

[out]

>>> arr
defaultdict(dict,
            {'abc': {'ef': 0.85, 'kl': 0.21, 'xyz': 0.923},
             'cldex': {'plax': 0.123, 'lion': -0.831}})

Наличие вложенной структуры dict не так удобно, как структура scipy разреженной матрицы.

Есть ли способ легко прочитать файл в указанном выше формате в любой из scipy объектов с разреженной матрицей?

Ответы [ 3 ]

0 голосов
/ 06 января 2019

Учитывая, что у вас есть dict

dox = {'abc': {'ef': 0.85, 'kl': 0.21, 'xyz': 0.923},'cldex': {'plax': 0.123, 'lion': -0.831}}

, это должно помочь вам доставить его в sparsematrix:

indptr = [0]
indices = []
data = []
vocabulary = {}

for d in dox:
     for term in dox[d]:
         index = vocabulary.setdefault(term, len(vocabulary))
         indices.append(index)
         data.append(dox[d][term])
         indptr.append(len(indices))

mat = csr_matrix((data, indices, indptr), dtype=float)

Это использует пример Сципи для приращенияматричная сборка.Вот вывод:

mat.todense()

enter image description here

0 голосов
/ 06 января 2019

В настоящее время, в версии 0.23, панды реализовали редкие версии Series и Data-Frames.По совпадению ваши данные можно рассматривать как Серии с многоуровневым индексом, так что вы можете использовать этот факт для построения разреженной матрицы.Кроме того, если он согласован, ваш формат можно прочитать, используя несколько строк панд, например:

import numpy as np
import pandas as pd
from io import StringIO

lines = StringIO("""abc
ef  0.85
kl  0.21
xyz 0.923
cldex
plax    0.123
lion    -0.831""")

# load Series
s = pd.read_csv(lines, delim_whitespace=True, header=None, names=['k', 'v'])
s = s.assign(k2=pd.Series(np.where(np.isnan(s.v), s.k, np.nan)).ffill())
result = s[~np.isnan(s.v)].set_index(['k2', 'k']).squeeze()

# convert to sparse matrix (csr)
ss = result.to_sparse()
coo, rows, columns = ss.to_coo(row_levels=['k'], column_levels=['k2'], sort_labels=True)
print(coo.tocsr())

Вывод

  (0, 0)    0.85
  (1, 0)    0.21
  (2, 1)    -0.831
  (3, 1)    0.12300000000000001
  (4, 0)    0.9229999999999999

Метод to_coo возвращает не только матрицу, но также столбцы и метки строк, следовательно, делает также обратное отображение.В приведенном выше примере возвращается следующее:

['ef', 'kl', 'lion', 'plax', 'xyz']
['abc', 'cldex']

Где 'ef' соответствует индексу 0 строк, а 'abc' соответствует индексу 0 столбцов.

0 голосов
/ 31 декабря 2018

Преобразовав комментарий @ hpaulj в ответ, вы можете многократно добавлять его в списки индексов строк и столбцов.Позже, разложите их на множители, используя pd.factorize, np.unique или sklearn * LabelEncoder, и преобразуйте в разреженные coo_matrix.

from scipy import sparse
import numpy as np
import pandas as pd

rows, cols, values = [], [], []
for line in x.splitlines():
   if ' ' not in line.strip():
       ridx = line
   else:
       cidx, value = line.strip().split()       
       rows.append(ridx)
       cols.append(cidx)
       values.append(value)

rows, rinv = pd.factorize(rows)
cols, cinv = pd.factorize(cols)

sp = sparse.coo_matrix((values, (rows, cols)), dtype=np.float32)
# sp = sparse.csr_matrix((np.array(values, dtype=np.float), (rows, cols)))

sp.toarray()
array([[ 0.85 ,  0.21 ,  0.923,  0.   ,  0.   ],
       [ 0.   ,  0.   ,  0.   ,  0.123, -0.831]], dtype=float32)

При необходимости вы можете использовать rinv и cinv для выполнения обратного отображения (преобразования индексов в строки).

...