【问题标题】:Why is pandas.grouby.mean so much faster than paralleled implementation为什么 pandas.groupby.mean 比并行实现快得多
【发布时间】:2025-12-12 07:30:01
【问题描述】:

我在一个非常大的数据集上使用了如下的 pandas grouby mean 函数:

import pandas as pd
df=pd.read_csv("large_dataset.csv")
df.groupby(['variable']).mean() 

看起来该函数没有使用多处理,因此,我实现了一个并行版本:

import pandas as pd 
from multiprocessing import Pool, cpu_count 

def meanFunc(tmp_name, df_input): 
    df_res=df_input.mean().to_frame().transpose()
    return df_res 

def applyParallel(dfGrouped, func):
    num_process=int(cpu_count())
    with Pool(num_process) as p: 
        ret_list=p.starmap(func, [[name, group] for name, group in dfGrouped])
    return pd.concat(ret_list)

applyParallel(df.groupby(['variable']), meanFunc)

但是,pandas 实现似乎仍然比我的并行实现快方式

我正在查看 pandas groupby 的 source code,我发现它正在使用 cython。是这个原因吗?

def _cython_agg_general(self, how, alt=None, numeric_only=True,
                        min_count=-1):
    output = {}
    for name, obj in self._iterate_slices():
        is_numeric = is_numeric_dtype(obj.dtype)
        if numeric_only and not is_numeric:
            continue

        try:
            result, names = self.grouper.aggregate(obj.values, how,
                                                   min_count=min_count)
        except AssertionError as e:
            raise GroupByError(str(e))
        output[name] = self._try_cast(result, obj)

    if len(output) == 0:
        raise DataError('No numeric types to aggregate')

    return self._wrap_aggregated_output(output, names)

【问题讨论】:

  • 我猜主要原因是您的代码必须花费大量时间将“本机”Pandas 数据帧(C 对象)转换为 Python 对象并返回。

标签: python python-3.x pandas cython pandas-groupby


【解决方案1】:

简短回答 - 如果您希望此类情况的并行性,请使用 dask。你的方法中有它避免的陷阱。它仍然可能不会更快,但会给你最好的机会,并且在很大程度上是 pandas 的替代品。

更长的答案

1) 并行本质上会增加开销,因此理想情况下,您要并行的操作有点昂贵。将数字相加并不是特别 - 在这里使用 cython 是对的,您正在查看的代码是调度逻辑。实际的核心 cython 是 here,它转化为一个非常简单的 c-loop。

2) 您正在使用多处理 - 这意味着每个进程都需要获取数据的副本。这是昂贵的。通常,由于 GIL,您必须在 python 中执行此操作 - 您实际上可以(并且 dask 确实)在这里使用线程,因为 pandas 操作在 C 中并释放 GIL。

3) 正如@AKX 在 cmets 中指出的那样 - 并行化之前的迭代 (... name, group in dfGrouped) 也相对昂贵 - 它为每个组构建新的子数据帧。原始的 pandas 算法对数据进行迭代。

【讨论】:

    最近更新 更多