Преобразовать разреженную матрицу в фрейм данных - PullRequest
1 голос
/ 28 апреля 2020

У меня есть разреженная матрица, в которой хранятся вычисленные сходства между набором документов. Матрица ndarray.

         0         1         2         3         4          
0        1.000000  0.000000  0.000000  0.000000  0.000000  
1        0.000000  1.000000  0.067279  0.000000  0.000000  
2        0.000000  0.067279  1.000000  0.025758  0.012039  
3        0.000000  0.000000  0.025758  1.000000  0.000000  
4        0.000000  0.000000  0.012039  0.000000  1.000000  

Я хотел бы преобразовать эти данные в трехмерный кадр данных следующим образом.

docA docB similarity
1    2    0.067279
2    3    0.025758
2    4    0.012039

Этот конечный результат не содержит диагоналей матрицы или нулевых значений. Он также перечисляет каждую пару документов только один раз (т.е. только в одной строке). Есть ли встроенный / эффективный метод для достижения этого конечного результата? Любые указатели будут высоко оценены.

Спасибо!

1 Ответ

2 голосов
/ 28 апреля 2020

Преобразование кадра данных в массив:

x = df.to_numpy()

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

i, j = np.triu_indices_from(x, k=1)
v = x[i, j]
ijv = np.concatenate((i, j, v)).reshape(3, -1).T
ijv = ijv[v != 0.0]

Преобразование вернемся к фрейму данных:

df_ijv = pd.DataFrame(ijv)

Я не уверен, что это быстрее или что-то еще, но альтернативный способ сделать средний шаг - преобразовать массив numpy в ijv или "тройная" разреженная матрица:

from scipy import sparse
coo = sparse.coo_matrix(x)
ijv = np.concatenate((coo.row, coo.col, coo.data)).reshape(3, -1).T

Теперь, учитывая симметричную c матрицу расстояний, все, что вам нужно сделать, это сохранить ненулевые элементы в верхнем правом треугольнике. Вы могли бы через это пройти oop. Или вы можете предварительно замаскировать массив с помощью np.triu_indices_from(x, k=1), но это побеждает всю цель этого предположительно более быстрого метода ... хммм.

...