Python 迭代中每行的并行处理

Python 迭代中每行的并行处理,python,pandas,multiprocessing,Python,Pandas,Multiprocessing,我有df_水果,这是水果的数据帧 index name 1 apple 2 banana 3 strawberry 并且,它的市场价格在mysql数据库中,如下所示 category market price apple A 1.0 apple B 1.5 banana A 1.2 banana

我有
df_水果
,这是水果的数据帧

index      name
1          apple
2          banana
3          strawberry
并且,它的市场价格在mysql数据库中,如下所示

category      market      price
apple         A           1.0
apple         B           1.5
banana        A           1.2
banana        A           3.0
apple         C           1.8
strawberry    B           2.7        
...
df_fruits
的迭代过程中,我想做一些处理

下面的代码是非并行版本

def process(fruit):
   # make DB connection
   # fetch the prices of fruit from database
   # do some processing with fetched data, which takes a long time
   # insert the result into DB
   # close DB connection

for idx, f in df_fruits.iterrows():
    process(f)
我想做的是对
df_fiults
中的每一行并行处理
,因为
df_fiults
有很多行,并且市场价格的表大小相当大(获取数据需要很长时间)

如您所见,行之间的执行顺序无关紧要,并且没有共享数据

df_fruits
中的迭代中,我不知道在哪里可以找到'pool.map()。我是否需要在并行执行之前分割行,并将块分配给每个进程?(如果是这样,则比其他进程更早完成其工作的进程将处于空闲状态?)

我研究过pandarallel,但我不能使用它(我的操作系统是windows)


任何帮助都将不胜感激。

是的,这是可能的,尽管熊猫图书馆并没有直接提供

也许你可以尝试这样做:

def do_parallel_stuff_on_dataframe(df, fn_to_execute, num_cores):
    # create a pool for multiprocessing
    pool = Pool(num_cores)

    # split your dataframe to execute on these pools
    splitted_df = np.array_split(df, num_cores)

    # execute in parallel:
    split_df_results = pool.map(fn_to_execute, splitted_df)

    #combine your results
    df = pd.concat(split_df_results)

    pool.close()
    pool.join()
    return df

您可能可以执行以下操作:

with Pool() as pool:
    # create an iterator that just gives you the fruit and not the idex
    rows = (f for _, f in df_fruits.iterrows())
    pool.imap(process, rows)

如果您不关心结果,或者愿意以任何顺序获得结果,或者不关心结果,则可能需要使用map以外的其他池原语之一。

根本不需要使用
pandas
。您只需使用包中的
Pool.map()
接受两个输入:一个函数和一个值列表

因此,您可以:

来自多处理导入池的

n=5#任意数量的螺纹
将池(n)作为p:
p、 映射(进程,df_水果['name'].值)
这将逐个遍历
df_fruits
数据帧中的所有结果。请注意,这里没有返回结果,因为
进程
函数旨在将结果写回数据库


如果您想在每一行中拥有多个列,则可以更改<代码> DFI-水果[[名称] ],值 >:

df_fruits[cols]。to_dict('records'))
这将提供一个字典作为
预处理
的输入,例如:

{'name':'apple','index':1,…}

数据有多大?@Yash嗯,我不能确切地说,但仅仅获取市场价格有时需要几分钟的时间。问题不仅在于数据的大小,还在于数据库的结构差(这使得获取需要更长的时间)。谢谢您的回答。在
process
函数中,我需要访问其他列值进行处理。虽然我只传递了
df_fruits['name'],但我是否可以访问
过程中的其他列?@W.Cointreau:不,您不能。但是,您可以使用
df_fruits['name'].values
,而不是使用
df_fruits[cols].values
(要考虑的列是
cols
)。或者您可以简单地使用
df_.values
。这将为您提供列表形式的值。通常使用字典比较容易,所以您可以尝试使用
df\u fruits.to\u dict('records')
。由于
process
函数有更多的参数,所以我也提到了。最后,我需要使用
partial
比如
func=partial(process,param1,param2…
,然后使用
pool.map(func,df_.to_dict('records'))
。非常感谢!啊,我从来没有听说过
imap
。我从这里找到了一些知识:。谢谢。实际上,我刚刚尝试了一个实验,
map
似乎比
imap
对100000个元素的快速操作要快。所有这些都允许迭代器作为参数。实验一下,看看哪一个对y最有效当然,我们不知道您是否需要处理的结果。好的,我会试试。我希望
imap
可以比
map
更快,因为在
process
中获取数据是主要的瓶颈,而且每个作业都不会影响其他作业。当我尝试与几个工作人员一起使用
map
时,他们中的一些人似乎在等待虽然他们不需要等待,但彼此都要完成。。。