熊猫轻松进行并行/多进程计算

时间:2019-03-15 22:02:48

标签: python pandas multiprocessing data-science python-multiprocessing

我正在寻找一种快速且易于使用的解决方案来对熊猫进行并行计算。我知道这对数据科学来说是一个非常重要的话题,但我发现并没有比标准大熊猫df.apply功能和整体简单更快 >快速实施!

所以...

让我们快速浏览一下那里可用的工具/框架。当然,我确实假设不谈论asyncio,它与我的主题没有直接关系。

黄昏

请在https://towardsdatascience.com/how-i-learned-to-love-parallelized-applies-with-python-pandas-dask-and-numba-f06b0b367138上找到一篇不错的文章 或直接在Dask网站上:http://docs.dask.org/en/latest/use-cases.html

在一个当前不起作用的代码段下面找到,但是对我们提供了一个很好的实现思路:

from dask import dataframe as dd
from dask.multiprocessing import get
from multiprocessing import cpu_count

cores = cpu_count()

dd.from_pandas(my_df,npartitions=cores).\
   map_partitions(
      lambda df : df.apply(
         lambda x : nearest_street(x.lat,x.lon),axis=1)).\
   compute(get=get)

我个人觉得这个实现非常痛苦(好吧,马比,我是个懒惰的人),但是总的来说,我发现这个实现不是很快,有时甚至比旧式df[feature] = df.feature.apply(my_funct)


多处理

在下面的代码段中查找以轻松运行多进程任务,但是使用HDD IO。该实现是否可以工作,但可以使我们对代码实现非常了解

import os
from multiprocessing import Process, cpu_count
from math import ceil
from tqdm import tqdm
import numpy as np


def chunks(l, n) :
    numbs =  [ceil(i) for i in np.linspace(0,len(l)+1, n+1)]    
    pairs = list()
    for i, val in enumerate(numbs) : 
        try : 
            pairs.append((numbs[i], numbs[i+1]))
        except : 
            return pairs

def my_funct(i0=0, i1=10000000) : 
    for n in tqdm(features[i0:i1]) :
        _df = df.loc[df.feature == n, :]
        _df = do_something_complex(_df)
        _df.to_csv(f"{my_path}/feat-{n}.csv", index=False)


# multiprocessing
cores = cpu_count()
features = df.feature.unique()
if cores < 2 : 
    my_funct(i0=0, i1=100000000)
else : 
    chks  = chunks(features, cores)
    process_list = [Process(target=my_funct, args=chk) \
                    for chk in chks]
    [i.start() for i in process_list]
    [i.join()  for i in process_list]

# join files and 'merge' in our new_df 
new_df = pd.DataFrame(columns=df.columns)
for filename in os.listdir(my_path) : 
    new_df = new_df.append(pd.read_csv(f'{my_path}/{filename}'),\
                           axis=0, ignore_index=True)
    os.remove(f'{my_path}/{filename}')

好吧,这种实现方法有些过激,但是1 /大多数情况下都能奏效,2 /易于理解,3 /比df = df.apply(my_funct)更快,有时甚至比Dask更快

...假设我无法从统计学上成为处理此类话题的唯一/第一人...

能帮我吗? 有什么解决办法吗? 是否有类似的东西:

  • df.multi_process_apply(my_funct)
  • df.parralel_apply(my_func)

非常感谢!

1 个答案:

答案 0 :(得分:1)

您可以尝试Pandarallel

免责声明::我是这个库的作者(该库仍在开发中,但是您已经可以用它取得良好的效果)。

不进行并行化: enter image description here

具有并行化功能: enter image description here

只需将df.apply(func)替换为df.parallel_apply(func),您的所有CPU都将被使用。