Как вычислить точечный продукт между каждой строкой из двух столбцов pandas с разреженными векторами

У меня есть фреймворк Pandas с двумя столбцами, каждый из которых содержит разреженный вектор SciPy в каждой строке. Эти векторы представляют собой строки из матриц csr (так что на самом деле они являются матрицами формы 1x8500).

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

Я знаю, как это сделать с apply / map в каждой строке, но это занимает так много времени, когда я работаю с наборами данных с миллионами строк. Есть ли более быстрый способ сделать это для всего фрейма данных?

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

Обновление: я не могу поделиться фактическими данными здесь, но вот игрушечный пример (обратите внимание, что на данный момент у меня есть только итоговый фрейм данных):

import pandas as pd
import numpy as np
from scipy.sparse import csr_matrix
row = np.array([0, 0, 1, 2, 2, 2])
col = np.array([0, 2, 2, 0, 1, 2])
data = np.array([1, 2, 3, 4, 5, 6])
mat = csr_matrix((data, (row, col)), shape=(3, 3))
df = pd.DataFrame({'Col_1': [mat.getrow(i) for i in range(3)],
                   'Col_2': [mat.getrow(i)*2 for i in range(3)]})

Я знаю, что могу сделать что-то вроде этого для вычисления скалярного произведения:

df['Col_3'] = df.apply(lambda row: np.dot(row['Col_1'],
                       row['Col_2'].transpose()).toarray()[0][0], axis=1)

Но есть ли более эффективный способ вычислить это Col_3?


person Sergey Zakharov    schedule 29.05.2017    source источник
comment
можете ли вы предоставить небольшой воспроизводимый набор данных выборки и желаемый набор данных?   -  person MaxU    schedule 29.05.2017
comment
Чтобы прояснить: действительно ли элементы в вашем фрейме данных являются разреженными векторами? Что-то мне подсказывает, что это неоптимальный дизайн. Вам действительно нужно добавить панд в картину?   -  person Andras Deak    schedule 29.05.2017
comment
Насколько велики ваши наборы данных?   -  person edesz    schedule 29.05.2017
comment
@AndrasDeak Строго говоря, это разреженные матрицы (csr), содержащие всего одну строку и около 8500 столбцов. Я стараюсь работать с пандами, потому что пользовательский код требует дополнительного тестирования.   -  person Sergey Zakharov    schedule 29.05.2017
comment
@WR Это десятки миллионов строк. Использование apply и np.dot на этих структурах заставляет меня ждать десятки минут.   -  person Sergey Zakharov    schedule 29.05.2017
comment
Я очень хорошо знаком с csr матрицами и хорошо знаком с пандами. разреженные кадры данных / серии. Продемонстрируйте, как вы создаете свой фрейм данных (на небольшом примере я могу копировать и вставлять). Мне нужно более четкое представление о том, что означает, что столбец содержит разреженную матрицу.   -  person hpaulj    schedule 29.05.2017
comment
Сначала я подумал, что каждый из ваших двух столбцов содержит значения из разреженной матрицы, по одному числу на строку на столбец. Но при дальнейшем чтении звучит так, будто столбцы представляют собой объект dtype, а каждая ячейка представляет собой большую разреженную матрицу. Только так dot продукт имеет смысл. В этом случае вы повторяете строки и делаете A[i]*B[i].T (или np.dot(A[i],B[i].T))   -  person hpaulj    schedule 29.05.2017
comment
@MaxU Я не могу предоставить никаких реальных данных, но добавил небольшой пример.   -  person Sergey Zakharov    schedule 29.05.2017
comment
@hpaulj Я только что обновил свой вопрос игрушечным примером.   -  person Sergey Zakharov    schedule 29.05.2017
comment
@SergeyZakharov, не могли бы вы опубликовать результат print(df.dtypes) и print(type(df.iloc[0,0]))?   -  person MaxU    schedule 30.05.2017
comment
Попробуйте это: df['Col_3'] = df['Col_1'].values.dot(df['Col_2'].values)   -  person MaxU    schedule 30.05.2017
comment
@MaxU это поднимает ValueError: dimension mismatch   -  person Sergey Zakharov    schedule 30.05.2017
comment
@SergeyZakharov, я думаю, нам понадобятся воспроизводимые наборы данных, чтобы мы могли вам помочь.   -  person MaxU    schedule 30.05.2017
comment
@MaxU Результат для print(df.dtypes) object для обоих столбцов. Результат для print(type(df.iloc[0,0])) - <class 'scipy.sparse.csr.csr_matrix'>.   -  person Sergey Zakharov    schedule 30.05.2017
comment
@MaxU, тот, который я дал в качестве обновления / редактирования моего вопроса, воспроизводится. Вы можете легко воспроизвести его, скопировав / вставив в среду Python. Я так и сделал, работает.   -  person Sergey Zakharov    schedule 30.05.2017
comment
@SergeyZakharov, вау! каждая ячейка вашего DF представляет собой разреженный массив?!? Думаю, будет больно работать с такой структурой данных ... А нельзя вместо этого создать 3D SparseArray?   -  person MaxU    schedule 30.05.2017
comment
@MaxU Извините, я не понимаю, о чем вы.   -  person Sergey Zakharov    schedule 30.05.2017
comment
@SergeyZakharov, Pandas не предназначен для работы с такими структурами данных, где вы пытаетесь поместить сложные объекты (разреженные массивы в вашем случае) в каждую ячейку. Это похоже на хранение таблицы в каждой строке таблицы в мире СУБД. Вы потеряете главную силу Pandas - быстрые векторизованные операции.   -  person MaxU    schedule 30.05.2017
comment
@MaxU Понятно. Постараюсь восстановить мой конвейер.   -  person Sergey Zakharov    schedule 30.05.2017


Ответы (1)


С твоим примером

matA = mat
matB = mat*2
col3 = (matA.multiply(matB)).sum(axis=1)

[[ 10]
 [ 18]
 [154]]

for i in range(3):
    print(df['Col_1'][i].A, df['Col_2'][i].A)
[[1 0 2]] [[2 0 4]]
[[0 0 3]] [[0 0 6]]
[[4 5 6]] [[ 8 10 12]]

df['Col_1'] dtype - это объект, а каждый элемент - это csr матрица, результат mat.getrow(i). Дисплей немного беспорядочный, со встроенными вкладками и новой строкой. Плотный эквивалент, произведенный с .A, красивее. Форма одинакова, но количество ненулевых членов варьируется.

person hpaulj    schedule 29.05.2017
comment
Я не могу использовать это, так как у меня нет матриц. Все, что у меня есть, это два столбца Col_1 и Col_2. И, конечно же, фреймворк. - person Sergey Zakharov; 30.05.2017
comment
Пока я просто пытаюсь прояснить действие. Построение многострочных разреженных матриц из этих столбцов панд, вероятно, представляет собой столько же работы, сколько выполнение пары dot за парой. Как только вы разбиваете вещи на массивы объектов, в numpy или pandas, вы теряете большую часть скорости настоящих числовых массивов. - person hpaulj; 30.05.2017