Ищете элегантное решение, которое позволяет избежать слияния двух фреймов - PullRequest
1 голос
/ 08 марта 2019

У меня есть dask dataframe df, который выглядит следующим образом:

Main_Author PaperID
A           X
B           Y
C           Z

У меня также есть еще один dask dataframe pa, который выглядит следующим образом:

PaperID  Co_Author
X        D
X        E
X        F
Y        A
Z        B
Z        D

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

Main_Author  Co_Authors   Num_Co_Authors
A            (D,E,F)      3
B            (A)          1
C            (B,D)        2

Вот что я сделал:

df = df.merge(pa, on="PaperID")

df = df.groupby('Main_Author')['Co_Author'].apply(lambda x: tuple(x)).reset_index()

df['Num_Co_Authors'] = df['Co_Author'].apply(lambda x: len(x))

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

1 Ответ

1 голос
/ 09 марта 2019

Если вы хотите работать с двумя большими DataFrame с, то вы можете попробовать обернуть это merge в dask.delayed

Импорт

from faker import Faker
import pandas as pd
import dask
from dask.diagnostics import ProgressBar
import random
fake = Faker()

Создание фиктивных данных для получения большого количества строк в каждом DataFrame

  • Укажите количество строк фиктивных данных для генерации в каждом DataFrame
number_of_rows_in_df = 3000
number_of_rows_in_pa = 8000

Создание большого набора данных с использованием библиотеки faker (за этот пост SO )

def create_rows(auth_colname, num=1):
    output = [{auth_colname:fake.name(),
               "PaperID":random.randint(1000,2000)} for x in range(num)]
    return output
df = pd.DataFrame(create_rows("Main_Author", number_of_rows_in_df))
pa = pd.DataFrame(create_rows("Co_Author", number_of_rows_in_pa))

Печать первых 5 строк данных

print(df.head())
       Main_Author  PaperID
0   Kyle Morton MD     1522
1    April Edwards     1992
2  Rachel Sullivan     1874
3    Kevin Johnson     1909
4     Julie Morton     1635

print(pa.head())
        Co_Author  PaperID
0  Deborah Cuevas     1911
1     Melissa Fox     1095
2    Sean Mcguire     1620
3     Cory Clarke     1424
4     David White     1569

Обернуть операцию merge во вспомогательной функции

def merge_operations(df1, df2):
    df = df1.merge(df2, on="PaperID")
    df = df.groupby('Main_Author')['Co_Author'].apply(lambda x: tuple(x)).reset_index()
    df['Num_Co_Authors'] = df['Co_Author'].apply(lambda x: len(x))
    return df

Dask подход - Генерация окончательного DataFrame с использованием dask.delayed

ddf = dask.delayed(merge_operations)(df, pa)
with ProgressBar():
    df_dask = dask.compute(ddf)

Выход Dask подход

[                                        ] | 0% Completed |  0.0s
[                                        ] | 0% Completed |  0.1s
[                                        ] | 0% Completed |  0.2s
[                                        ] | 0% Completed |  0.3s
[                                        ] | 0% Completed |  0.4s
[                                        ] | 0% Completed |  0.5s
[########################################] | 100% Completed |  0.6s

print(df_dask[0].head())
      Main_Author                                          Co_Author  Num_Co_Authors
0  Aaron Anderson  (Elizabeth Peterson, Harry Gregory, Catherine ...              15
1    Aaron Barron  (Martha Neal, James Walton, Amanda Wright, Sus...              11
2      Aaron Bond  (Theresa Lawson, John Riley, Daniel Moore, Mrs...               6
3  Aaron Campbell  (Jim Martin, Nicholas Stanley, Douglas Berry, ...              11
4  Aaron Castillo  (Kevin Young, Patricia Gallegos, Tricia May, M...               6

Подход Pandas - Генерация окончательного DataFrame, созданного с использованием Pandas

df_pandas = (merge_operations)(df, pa)

print(df_pandas.head())
      Main_Author                                          Co_Author  Num_Co_Authors
0  Aaron Anderson  (Elizabeth Peterson, Harry Gregory, Catherine ...              15
1    Aaron Barron  (Martha Neal, James Walton, Amanda Wright, Sus...              11
2      Aaron Bond  (Theresa Lawson, John Riley, Daniel Moore, Mrs...               6
3  Aaron Campbell  (Jim Martin, Nicholas Stanley, Douglas Berry, ...              11
4  Aaron Castillo  (Kevin Young, Patricia Gallegos, Tricia May, M...               6

Сравнить DataFrame s, полученные с использованием подходов Pandas и Dask

from pandas.util.testing import assert_frame_equal
try:
    assert_frame_equal(df_dask[0], df_pandas, check_dtype=True)
except AssertionError as e:
    message = "\n"+str(e)
else:
    message = 'DataFrames created using Dask and Pandas are equivalent.'

Результат сравнения двух подходов

print(message)
DataFrames created using Dask and Pandas are equivalent.
...