为什么pandas.grouby.mean比并行实现快得多

时间:2019-02-04 11:17:37

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

我在非常大的数据集上使用了如下的pandas grouby均值函数:

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)

但是,熊猫的实现似乎仍然比我的并行实现快前进

我正在查看source code for pandas groupby,发现它正在使用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)

1 个答案:

答案 0 :(得分:1)

简短的回答-如果您希望此类情况并行使用,请使用dask。您的方法存在陷阱,可以避免。它可能仍未达到更快的速度,但可以为您提供最佳拍摄效果,是熊猫的主要替代品。

更长的答案

1)并行性本质上会增加开销,因此理想情况下,要并行执行的操作会有些昂贵。累加数字并不是特别重要-您​​在这里使用cython是正确的,您正在查看的代码是调度逻辑。实际的核心cython是here,它转换为非常简单的c循环。

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

3)正如@AKX在注释中指出的那样-并​​行化(std::string)之前的迭代也相对昂贵-为每个组构造新的子数据帧。原始的pandas算法会对数据进行迭代。