【问题标题】:Pandas: efficient way to combine dataframesPandas:组合数据框的有效方法
【发布时间】:2019-04-27 06:54:13
【问题描述】:

我正在寻找一种比 pd.concat 更有效的方法来组合两个 pandas DataFrame。

我有一个很大的 DataFrame(大小约为 7GB),其中包含以下列 - “A”、“B”、“C”、“D”。我想按“A”对框架进行分组,然后为每个组: 按“B”分组,平均“C”并对“D”求和,然后将所有结果合并到一个数据帧中。我尝试了以下方法 -

1) 创建一个空的最终 DataFrame,迭代“A”的 groupby 进行我需要的处理,然后 pd.concat 每组最后一个 DataFrame。问题是 pd.concat 非常慢。

2) 遍历“A”的 groupby,进行我需要的处理,然后将结果保存到 csv 文件中。这工作正常,但我想知道是否有更有效的方法不涉及写入磁盘的所有 I/O。

代码示例

第一种方法 - 带有 pd.concat 的最终 DataFrame:

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),但我没有发现它有帮助。

非常感谢! :)

【问题讨论】:

  • 为什么不使用 multiIndex 进行 groupby,这样您就可以一次性按“A”和“B”进行分组,而不是遍历“A”组?这也将为您节省连接工作。你有一些样本数据吗?
  • 很遗憾,我无法提供示例数据。你能详细说明一下 grouby 多重索引吗?
  • 你考虑过 Dask 吗? docs.dask.org/en/latest

标签: python pandas performance split-apply-combine


【解决方案1】:

已解决

所以 Niels Henkens 的评论真的很有帮助,解决方案就是 -

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()

【讨论】:

    猜你喜欢
    • 2018-04-16
    • 1970-01-01
    • 2016-08-21
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    相关资源
    最近更新 更多