Pandas: эффективный способ объединения данных - PullRequest
0 голосов
/ 27 апреля 2019

Я ищу более эффективный способ, чем pd.concat, для объединения двух панд DataFrames.

У меня большой DataFrame (размером ~ 7 ГБ) со следующими столбцами - «A», «B», «C», «D». Я хочу сгруппировать кадр по «А», затем для каждой группы: сгруппировать по «B», усреднить «C» и сложить «D», а затем объединить все результаты в один кадр данных. Я пробовал следующие подходы -

1) Создание пустого окончательного DataFrame, итерация группы «A» для выполнения необходимой обработки, а затем pd.concat каждой группы в окончательном DataFrame. Проблема в том, что pd.concat работает очень медленно.

2) Итерация по группе «A», выполнение необходимой обработки и сохранение результата в CSV-файл. Это работает нормально, но я хочу выяснить, есть ли более эффективный способ, который не включает все операции ввода-вывода записи на диск.

Примеры кодов

Первый подход - окончательный DataFrame с pd.concat:

def pivot_frame(in_df_path):
    in_df = pd.read_csv(in_df_path, delimiter=DELIMITER)
    res_cols = in_df.columns.tolist()
    res = pd.DataFrame(columns=res_cols)
    g = in_df.groupby(by=["A"])
    for title, group in g:
        temp = group.groupby(by=["B"]).agg({"C": np.mean, "D": np.sum})
        temp = temp.reset_index()
        temp.insert(0, "A", title)
        res = pd.concat([res, temp], ignore_index=True)
        temp.to_csv(f, mode='a', header=False, sep=DELIMITER)
    return res

Второй подход - запись на диск:

def pivot_frame(in_df_path, ouput_path):
    in_df = pd.read_csv(in_df_path, delimiter=DELIMITER)
    with open(ouput_path, 'w') as f:
        csv_writer = csv.writer(f, delimiter=DELIMITER)
        csv_writer.writerow(["A", "B", "C", "D"])
        g = in_df.groupby(by=["A"])
        for title, group in g:
            temp = group.groupby(by=["B"]).agg({"C": np.mean, "D": np.sum})
            temp = temp.reset_index()
            temp.insert(0, JOB_TITLE_COL, title)
            temp.to_csv(f, mode='a', header=False, sep=DELIMITER)

Второй подход работает намного быстрее, чем первый, но я ищу что-то такое, что бы постоянно избавляло меня от доступа к диску. Я читал о split-apply-Объединить (например, - https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html), но я не нашел это полезным.

Большое спасибо! :)

1 Ответ

1 голос
/ 27 апреля 2019

решаемые

Так что комментарий Нильса Хенкенса действительно помог, и решение - просто ...

result = in_df.groupby(by=["A","B"]).agg({"C": np.mean, "D": np.sum})

Еще одним улучшением производительности является использование Dask -

import dask.dataframe as dd
df = dd.read_csv(PATH_TO_FILE, delimiter=DELIMITER)
g = df.groupby(by=["A", "B"]).agg({"C": np.mean, "D": np.sum}).compute().reset_index()
...