基于多列值的具有重复键的两个大型 Pandas DataFrame 的条件合并/连接 - Python

Posted

技术标签:

【中文标题】基于多列值的具有重复键的两个大型 Pandas DataFrame 的条件合并/连接 - Python【英文标题】:Conditional merge / join of two large Pandas DataFrames with duplicated keys based on values of multiple columns - Python 【发布时间】:2020-09-08 21:15:33 【问题描述】:

我来自 R,老实说,这是使用 R data.tables 在一行中做的最简单的事情,而且对于大型数据表的操作也相当快。 Bu 我真的很难在 Python 中实现它。前面提到的用例都不适合我的应用程序。手头的主要问题是 Python 解决方案中的内存使用情况,我将在下面解释。

问题:我有两个大的 DataFrames df1 和 df2(每个大约 50M-100M 行),我需要根据两个条件将 df2 的两(或 n)列合并到 df1:

1) df1.id = df2.id(合并的通常情况)

2) df2.value_2A

import numpy as np
import pandas as pd

df1 = pd.DataFrame('id': [1,1,1,2,2,3], 'value_1': [2,5,7,1,3,4])
df2 = pd.DataFrame('id': [1,1,1,1,2,2,2,3], 'value_2A': [0,3,7,12,0,2,3,1], 'value_2B': [1,5,9,15,1,4,6,3])

df1
Out[13]: 
   id  value_1
0   1        2
1   1        5
2   1        7
3   2        1
4   2        3
5   3        4

df2
Out[14]: 
   id  value_2A  value_2B
0   1         0         1
1   1         3         5
2   1         7         9
3   1        12        15
4   2         0         1
5   2         2         4
6   2         3         6
7   3         1         3

desired_output
Out[15]: 
   id  value_1  value_2A  value_2B
0   1        2       NaN       NaN
1   1        5       3.0       5.0
2   1        7       7.0       9.0
3   2        1       0.0       1.0
4   2        3       2.0       4.0
5   2        3       3.0       6.0
6   3        4       NaN       NaN

现在,我知道这可以通过首先以“左”方式合并 df1 和 df2 然后过滤数据来完成。但就缩放而言,这是一个可怕的解决方案。我有 50M x 50M 行,其中有多个重复的 id。这将创建一些我必须过滤的巨大数据框。

## This is NOT a solution because memory usage is just too large and 
## too many oprations deeming it extremely inefficient and slow at large scale

output = pd.merge(df1, df2, on='id', how='left')  ## output becomes very large in my case
output.loc[~((output['value_1'] >= output['value_2A']) & (output['value_1'] <= output['value_2B'])), ['value_2A', 'value_2B']] = np.nan
output = output.loc[~ output['value_2A'].isnull()]
output = pd.merge(df1, output, on=['id', 'value_1'], how='left')

这太低效了。我正在合并一个大型数据集两次以获得所需的输出并在此过程中创建大量数据帧。呸!

将此视为两个事件数据帧,我试图将它们匹配在一起。也就是说,标记 df1 的事件是否在 df2 的事件中发生。 df1 和 df2 中的每个 id 都有多个事件。 df2 的事件不是互斥的。条件加入确实需要在加入时发生,而不是在加入之后。 这在 R 中很容易完成:

## in R realm ##
require(data.table)
desired_output <- df2[df1, on=.(id, value_2A <= value_1, value_2B >= value_1)] #fast and easy operation

有没有办法在 Python 中做到这一点?

【问题讨论】:

df1.merge(df1.merge(df2).query('value_2A&lt;=value_1&lt;=value_2B'), how = 'left') 应该可以工作;然而 5000 万行对于 Pandas 来说似乎很多。您可以为此坚持使用 rdatatable 或 SQL 【参考方案1】:

有趣的问题!

看起来 pandasql 可能会做你想做的事。请参见 : How to do a conditional join in python Pandas?

【讨论】:

我已经尝试过了。它在此过程中使用相同数量的内存,而且速度非常慢。 :( 您的联接表中有多少行?以及选择了哪些字段?

以上是关于基于多列值的具有重复键的两个大型 Pandas DataFrame 的条件合并/连接 - Python的主要内容,如果未能解决你的问题,请参考以下文章

基于具有列表值的多列删除数据框中的重复行[重复]

一次在多列上使用 pandas groupby().apply(list) [重复]

如何通过多列理想地组合具有不同主键的两个表 HASH

pandas groupby 多列给出了奇怪的索引行为[重复]

Pandas:在多列中查找具有匹配值的行的 Pythonic 方法(分层条件)

与迭代两个大型 Pandas 数据框相比,效率更高