【问题标题】:How to merge two pandas dataframe in parallel (multithreading or multiprocessing)如何并行合并两个熊猫数据帧(多线程或多处理)
【发布时间】:2016-03-03 23:25:33
【问题描述】:

如果不进行并行编程,我可以使用下面的代码合并key 列上的左右数据帧,但它会太慢,因为两者都非常大。有什么办法可以有效地并行化吗?

我有 64 个核心,所以实际上我可以使用其中的 63 个来合并这两个数据帧。

left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                      'A': ['A0', 'A1', 'A2', 'A3'],
                     'B': ['B0', 'B1', 'B2', 'B3']})


right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                      'C': ['C0', 'C1', 'C2', 'C3'],
                      'D': ['D0', 'D1', 'D2', 'D3']})


result = pd.merge(left, right, on='key')

输出将是:

left:
    A   B key
0  A0  B0  K0
1  A1  B1  K1
2  A2  B2  K2
3  A3  B3  K3

right:
    C   D key
0  C0  D0  K0
1  C1  D1  K1
2  C2  D2  K2
3  C3  D3  K3

result:
    A   B key   C   D
0  A0  B0  K0  C0  D0
1  A1  B1  K1  C1  D1
2  A2  B2  K2  C2  D2
3  A3  B3  K3  C3  D3

我想并行执行此操作,以便快速完成。

【问题讨论】:

  • 即使“多线程”解决方案是可能的,您也必须将数据帧分解成块,并行合并它们(可能使用threading 模块),然后将这些块放回一起.所有这些只会将您的速度提高 >4 倍(假设您有 4 个内核)...
  • 我有 64 个核心,所以实际上我可以使用其中的 63 个来合并这两个数据帧。

标签: python multithreading pandas parallel-processing multiprocessing


【解决方案1】:

我相信你可以使用dask。 和函数merge

Docs说:

什么确实有效?

巧妙的并行化操作(也很快):

加入索引:dd.merge(df1, df2, left_index=True, right_index=True)

或者:

需要随机播放的操作(慢速,除非在索引上)

设置索引:df.set_index(df.x)

加入不在索引上:pd.merge(df1, df2, on='name')

您也可以查看Create Dask DataFrames.

示例

import pandas as pd

left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                      'A': ['A0', 'A1', 'A2', 'A3'],
                     'B': ['B0', 'B1', 'B2', 'B3']})


right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
                      'C': ['C0', 'C1', 'C2', 'C3'],
                      'D': ['D0', 'D1', 'D2', 'D3']})


result = pd.merge(left, right, on='key')
print result
    A   B key   C   D
0  A0  B0  K0  C0  D0
1  A1  B1  K1  C1  D1
2  A2  B2  K2  C2  D2
3  A3  B3  K3  C3  D3

import dask.dataframe as dd

#Construct a dask objects from a pandas objects
left1 = dd.from_pandas(left, npartitions=3)
right1 = dd.from_pandas(right, npartitions=3)

#merge on key
print dd.merge(left1, right1, on='key').compute()
    A   B key   C   D
0  A3  B3  K3  C3  D3
1  A1  B1  K1  C1  D1
0  A2  B2  K2  C2  D2
1  A0  B0  K0  C0  D0
#first set indexes and then merge by them
print dd.merge(left1.set_index('key').compute(), 
               right1.set_index('key').compute(), 
               left_index=True, 
               right_index=True)
      A   B   C   D
key                
K0   A0  B0  C0  D0
K1   A1  B1  C1  D1
K2   A2  B2  C2  D2
K3   A3  B3  C3  D3

【讨论】:

    【解决方案2】:

    您可以通过将 key 列设置为数据帧的索引并改用 join 来提高合并速度(在给定示例中提高了大约 3 倍)。

    left2 = left.set_index('key')
    right2 = right.set_index('key')
    
    In [46]: %timeit result2 = left2.join(right2)
    1000 loops, best of 3: 361 µs per loop
    
    In [47]: %timeit result = pd.merge(left, right, on='key')
    1000 loops, best of 3: 1.01 ms per loop
    

    【讨论】:

    • 这很好,但是合并几个keys... 仍然可以使用join 吗?即:pd.merge(left, right, on=['key1','key2']
    猜你喜欢
    • 1970-01-01
    • 2018-07-22
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-02
    相关资源
    最近更新 更多