2017-05-26 52 views
1

熊猫目前不支持SQL意义上的条件连接;然而,可以通过在公共字段上执行较大的连接,然后在后连接处理中应用过滤器来模拟(性能较低)。熊猫条件连接中保留左/右连接逻辑

但是,我正在寻找一种方法来通过此条件连接来保留左(或右)元素。我通过后期处理失去了它们。

import pandas 

# Create a dataframe 
df = pandas.DataFrame([{'name': 'A', 'start': '20171201', 'end': '20180205'}, {'name': 'A', 'start': '20170901', 'end': '20170905'}, {'name': 'B', 'start': '20190101', 'end': '20190205'}]) 
df['start'] = pandas.to_datetime(df['start']) 
df['end'] = pandas.to_datetime(df['end']) 
print df 


      end name  start 
    0 2018-02-05 A 2017-12-01 
    1 2017-09-05 A 2017-09-01 
    2 2019-02-05 B 2019-01-01 



# Create another dataframe, don't want to lose any data here. 
v_df = pandas.DataFrame([{'name': 'A', 'val': 10, 'date': '20180101'}, {'name': 'B', 'val': 20, 'date': '20170101'}]) 
v_df['date'] = pandas.to_datetime(v_df['date']) 
print v_df 

      date name val 
    0 2018-01-01 A 10 
    1 2017-01-01 B 20 



# Conditional Left Join both dataframes, want to avoid losing the name B val. 
v_df = v_df.merge(df, how='left', on=['name']) 
v_df = v_df[v_df['date'].between(v_df['start'], v_df['end'])] 
print v_df 


      date name val  end  start 
    0 2018-01-01 A 10 2018-02-05 2017-12-01 
在这种情况下

所需的输出应为以下,其中包括来自B.

 date name val  end  start 
0 2018-01-01 A 10 2018-02-05 2017-12-01 
2 2017-01-01 B 20  NaT  NaT 

一个left记录中的解决方案还需要能够处理的一般合并时,多条记录匹配,但是当没有一个组匹配条件时,将返回一个空记录(而不是任何记录)。

+0

你可以发布你想要的输出吗? “避免失去B val这个名字”的意思有点不清楚。你的意思是你想要'v_df ['end']'和'v_df ['start']'blank/NaN合并条件不满足的情况吗? – EFT

+0

@EFT是的,确切地说,我添加了所需的输出 – jab

+0

@EFT基本上,我们希望将记录筛选到没有返回的地方。在这种情况下(如果没有要返回),请将相应的字段设置为空白/ NaN。 – jab

回答

2
filter_df = df.merge(v_df) 
filter_df = filter_df[filter_df['date'].between(filter_df['start'], filter_df['end'])] 
v_df.merge(filter_df, how='left') 

应该回到你想要什么。 filter_df标识连接正确工作的行,您在问题中执行的操作,第二次合并将这些startend值仅附加到相关行。

编辑:

@ MaxU的回答是功能上等同和语法更优雅。

2

我不知道这是最好的办法,但似乎做的工作:

In [191]: v_df.merge(v_df.merge(df).query("start <= date <= end"), how='left') 
Out[191]: 
     date name val  end  start 
0 2018-01-01 A 10 2018-02-05 2017-12-01 
1 2017-01-01 B 20  NaT  NaT