Эффективные парные вычисления с пандами

1

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

Например, сравнение строки со значениями [1, 0, 0, 1] со строкой со значениями [0, 0, 1, 1] даст результирующее значение 2, так как индексы 0 и 2 различаются.

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

Однако я не знаю, как перевести его на код. Вот что я имею до сих пор:

shortened = pd.DataFrame(
    [{'c1':1, 'c2':0, 'c3':0}, {'c1':1,'c2':1, 'c3':0}, {'c1':0,'c2':0, 'c3':1}]
)
distm = [[""]+ list(shortened.index)]
found = {}
for index,row in shortened.iterrows():
    newrow = [index]
    for i2,r2 in shortened.iterrows():
        if((i2,index) in found):
            newrow.append(found[(i2,index)])
            continue
        if(index == i2):
            newrow.append(0)
            continue
        summeddif = sum(i != j for i, j in zip(row, r2))
        newrow.append(summeddif)
        found[(index,i2)] = summeddif
    distm.append(newrow)

Таким образом, с примером dataframe, получается правильный вывод:

  | 0 1 2
---------
0 | 0 1 2
1 | 1 0 3
2 | 2 3 0

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

Теги:
pandas
dataframe
loops
iteration

1 ответ

2
Лучший ответ

Используйте широковещательный XOR.

(shortened.values ^ shortened.values[:, None]).sum(2)

array([[0, 1, 2],
       [1, 0, 3],
       [2, 3, 0]])

XOR - самый простой (и самый быстрый) способ проверки того, являются ли два бита одинаковыми. Это должно работать до тех пор, пока ваш вход двоичный.

Обратите внимание, что это интенсивность памяти, особенно для очень больших кадров, с возможностью OOM на ~ 1M строках.

  • 0
    спасибо это круто! что означает .sum (2)? это константа?
  • 1
    @theupandup Это эквивалентно sum(axis=2) , что мне нужно было сделать, чтобы получить ожидаемый результат.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню