在多个条件下合并来自多个数据帧的数据

Posted

技术标签:

【中文标题】在多个条件下合并来自多个数据帧的数据【英文标题】:merge data from multiple data frames on multiple conditions 【发布时间】:2018-05-30 05:37:34 【问题描述】:

我想合并多个数据框,但前提是键匹配并且日期范围在 df1 中的“InitialAdmit”日期范围的 90 天内。我想保留 df1 中的所有行,并且只合并 df2、df3 等中的其他行,只要它们与键匹配并在日期范围内。

注意:先合并 dfs 然后考虑日期范围条件对我不起作用。我第一次使用这种方法,但是在很多情况下合并是成功的,但是由于日期范围超出了限制,我让脚本删除了行。我需要以某种方式保留 df1 中的所有行。

Python Pandas: Merging data frames on multiple conditions - 这个问题很相似,但它似乎合并然后应用条件。我认为更好的方法是应用条件,然后在满足条件时合并。不过,我愿意接受建议。

数据帧:

a = 'Key': [100000204, 100000255, 100000271,100000286,100000628], 
 'InitialAdmit': ['2012-06-04', '2012-05-03', '2012-01-16', '2012-10-26', '2012-02-21'],
 '90DayRange': ['2012-09-02', '2012-08-01', '2012-04-15', '2013-01-24', '2012-05-21']

df1 = pandas.DataFrame(data=a)
df1


b = 'Key': [100000208, 100000255, 100000723,100000286,100000866], 
 'InitialAdmit': ['2012-01-22', '2012-06-03', '2012-10-26', '2012-11-26', '2012-05-11'],

df2 = pandas.DataFrame(data=b)
df2 

c = 'Key': [100000255, 100000255, 100000702,100000221,100000628], 
 'InitialAdmit': ['2012-06-22', '2012-10-03', '2012-10-26', '2012-11-26', '2012-04-11'],

df3 = pandas.DataFrame(data=c)
df3

脚本:

df_NotIncludedRows = pandas.DataFrame()
df_final = pandas.DataFrame()
dfs = [df2] #I plan to add more dataframes so I'm iterating through this list of dfs 

for df in dfs: #iterate through each df in dfs
    for key in df1["Key"]: #iterate through each key found in column 'Id'
        if key in df["Key"]: # find any matching key from df1 in df2 (part of my issue exists here)
            if (df["Admit"] >= df1["InitialAdmit"]) | (df["Admit"] <= df1["90DayRange"]):
                df_final = pandas.merge(df1,df.loc[:],on='Key',how='left') # my df.loc[:] is a little off i think
            else:
                df_NotIncludedRows = df_NotIncludedRows.append(df.loc[:]) # same df.loc[:] issue i believe   
df_NotIncludedRows

【问题讨论】:

【参考方案1】:

我还是推荐先合并再过滤,这里我们使用布尔索引和combine_first

df=df1.merge(df2,on='Key')
m=(df.InitialAdmit_y>=df.InitialAdmit_x)&(df.InitialAdmit_y<=df.InitialAdmit_x)
df1.set_index('Key').combine_first(df[m].set_index('Key'))


Out[215]: 
          90DayRange InitialAdmit InitialAdmit_x InitialAdmit_y
Key                                                            
100000204 2012-09-02   2012-06-04            NaT            NaT
100000255 2012-08-01   2012-05-03     2012-05-03     2012-06-03
100000271 2012-04-15   2012-01-16            NaT            NaT
100000286 2013-01-24   2012-10-26     2012-10-26     2012-11-26
100000628 2012-05-21   2012-02-21            NaT            NaT

【讨论】:

跟进此方法。这很棒,似乎可以满足我的需要!那谢谢啦!但是我应该指定更多的背景:我有大约 25 个数据帧,每个数据帧大约有 500k mil - 3 mil 行。就速度和内存使用而言,过滤器然后合并方法是否会更有效地处理如此大的数据集? @MartyBobak 在合并之前我们不知道哪个是过滤器,这就是为什么我们需要先合并,我们需要找到值的范围然后过滤 这很公平。如果没问题,我想用另一个 df 扩展这个问题,因为我发现很难将你的答案应用于两个以上的 df。我使用: dfs = [df1, df2, df3] df_merged = reduce(lambda left,right: pandas.merge(left,right,on='Key',how='left'), dfs) -- 合并多个 dfs ,基本上取代了你的第一行。【参考方案2】:

考虑reduce 使用左连接进行链合并。下面演示了 3 个 df2 副本。此外,下面假设 InitialAdmit 是数据框的最后一列。根据需要重新排序。

import pandas 
import numpy
from functools import reduce    
...

# LIST OF DATAFRAMES WITH SUFFIXING OF INITIALADMIT TO AVOID NAME COLLISION
dfList = [d.rename(columns='InitialAdmit':'InitialAdmit_' + str(i)) 
          for i,d  in enumerate([df1, df2, df2, df2])]

# USER-DEFINED METHOD CONDITIONING ON LAST COLUMN
def mergefilter(x, y):
    tmp = pandas.merge(x, y, on='Key', how='left')
    tmp.loc[~(tmp.iloc[:, -1].between(tmp['InitialAdmit_0'], tmp['90DayRange'])), 
            tmp.columns[-1]] = numpy.nan

    return tmp

finaldf = reduce(mergefilter, dfList)

print(finaldf)
#    90DayRange InitialAdmit_0        Key InitialAdmit_1 InitialAdmit_2 InitialAdmit_3
# 0  2012-09-02     2012-06-04  100000204            NaN            NaN            NaN
# 1  2012-08-01     2012-05-03  100000255     2012-06-03     2012-06-03     2012-06-03
# 2  2012-04-15     2012-01-16  100000271            NaN            NaN            NaN
# 3  2013-01-24     2012-10-26  100000286     2012-11-26     2012-11-26     2012-11-26
# 4  2012-05-21     2012-02-21  100000628            NaN            NaN            NaN

【讨论】:

以上是关于在多个条件下合并来自多个数据帧的数据的主要内容,如果未能解决你的问题,请参考以下文章

为 pyspark 数据帧的每一行评估多个 if elif 条件

R:基于多个条件的两个数据帧的子集

迭代多个数据帧的合并

如何合并两个或多个具有不同 where 条件的查询?我必须重用在第一个代码中使用的代码

根据来自其他数据帧的位置条件在数据帧上编写选择查询,scala

如何基于多个条件更快地合并 2 个 pandas 数据帧