Панды: эффективный способ комбинировать фреймы данных

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

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

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

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

Примеры кода

Первый подход - Final 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)

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

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


person Guy    schedule 27.04.2019    source источник
comment
Почему бы не группировать с помощью multiIndex, чтобы можно было группировать по «A» и «B» за один раз, вместо того, чтобы перебирать группы «A»? Это также сэкономит вам усилия на конкатенацию. У вас есть образцы данных.   -  person Niels Henkens    schedule 27.04.2019
comment
К сожалению, я не могу предоставить образцы данных. Не могли бы вы подробнее рассказать о мультииндексе grouby?   -  person Guy    schedule 27.04.2019
comment
Вы думали о Даске? docs.dask.org/en/latest   -  person run-out    schedule 27.04.2019


Ответы (1)


Решено

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

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()
person Guy    schedule 27.04.2019