Оптимизация операции сравнения строк в pandas / python - PullRequest
0 голосов
/ 12 ноября 2018

У меня есть большой массив данных pandas, который в упрощенном виде выглядит так:

names = ['P1', 'P2', 'P3']
clusters = [1, 1, 2]

df = pd.DataFrame(clusters, names).reset_index()
df.columns=['names', 'cluster']
print(df)

  names  cluster
0    P1        1
1    P2        1
2    P3        2

Я хочу создать новый фрейм данных или массив df_, который выглядит следующим образом:

names  P1  P2  P3
names            
P1      1   1   0
P2      1   1   0
P3      0   0   1

Если значения ячеек указывают, имеют ли каждая пара (P1 / P2, P1 / P3, P2 / P3 и т. Д.) Одинаковое значение «кластера» в исходном кадре данных (df).

Я смог добиться этого с помощью грубой силы с помощью функции iterrows:

df_ = pd.DataFrame(index=df['names'], columns=df['names'])
df_ = df_.fillna(0)
for index, row in df.iterrows():
    for index2, row2 in df.iterrows():
        if row['cluster'] == row2['cluster']:
            df_.iloc[index, index2] += 1
        else: 
            continue

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

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Я бы использовал xarray для выполнения задачи и использовал бы функцию автоматического вещания .

import pandas as pd

names = ['P1', 'P2', 'P3']
clusters = [1, 1, 2]

df = pd.DataFrame(clusters, names).reset_index()
df.columns=['names_x', 'cluster']
da_x = df.set_index('names_x')['cluster'].to_xarray()

df.columns=['names_y', 'cluster']
da_y = df.set_index('names_y')['cluster'].to_xarray()

da= (da_x == da_y).astype(int)
print(da.to_dataframe('X').unstack(['names_y'])['X'])

Что здесь происходит?

Мы используем две разные версии DataFrame: одну, где имя столбца индекса равно names_x, а другую - names_y.

Мы выбираем один столбец, cluster, изDataFrame (превращая его в pandas.Series), затем примените метод to_xarray, который преобразует ряд в xarray.DataArray-s.

Теперь у нас есть два DataArrays: da_x и da_y, с разными размерами (names_x и names_y).Если мы теперь выполним какую-либо двоичную операцию с этим набором данных (например, ==), то xarray автоматически расширит каждый DataArray вдоль отсутствующих измерений перед применением самой операции.

Наконец, нам нужно повернуть его обратно к DataFrame и «pivot»используя метод unstack.

Таким образом, большая часть кода фактически является подготовительной, здесь происходит "волшебство":

da_x == da_y
0 голосов
/ 12 ноября 2018

Вы можете merge, а затем использовать .crosstab

import pandas as pd

m = df.merge(df, on='cluster')
pd.crosstab(m.names_x, m.names_y)

names_y  P1  P2  P3
names_x            
P1        1   1   0
P2        1   1   0
P3        0   0   1

Если вам нужно, чтобы для спаривания было просто boolean вместо счетчика, добавьте .clip(upper=1) кконец.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...