筛选另一个数据框以在另一个数据框中创建新列

时间:2020-04-27 12:52:11

标签: python pandas

我有2个数据框:

df1

id |tier |event_date
233|1    |2014-01-20
234|1    |2015-02-12
235|2    |2015-02-12

df2

id |join_date |stop_date
233|2013-03-12|2015-04-01
233|2016-03-12|2017-04-01
235|2013-03-12|2016-04-01

我想在df2has_tier_1has_tier_2

中创建两列

对于df2中的每一行,我想查看是否有一个基于id中的df1的匹配行。 df1中可能有多个匹配的行。:

如果存在匹配的行,那么我想检查event_date中的df1join_date中的stop_datedf2之间。如果是这样,则基于tier,相应列中的值为1。

目标是df2看起来像这样:

id |join_date |stop_date |has_tier_1| has_tier_2
233|2013-03-12|2015-04-01|    1     |  0
233|2016-03-12|2017-04-01|    0     |  0
235|2013-03-12|2016-04-01|    0     |  1

我创建了此功能:

def create_columns(x):
    x[has_tier_1] == 0
    x[has_tier_2] == 0
    if x['id'] in df1['id']:
        if x['join_date'] <= df1['event_date'] <= x['stop_date']:
            if df1['tier'] == '1':
                return has_tier_1 == 1
            elif df1['tier'] == '2':
                return has_tier_2 == 1
            else:
                return x[has_tier_1], x[has_tier_2] 

    else:
        return x[has_tier_1], x[has_tier_2] 

我申请了:

df1.apply(create_columns)

但是,我也没有得到正确的结果。请帮助我如何实现这一目标。

1 个答案:

答案 0 :(得分:0)

pandas的merge asof方法在这里派上用场,因为它允许我们根据距离合并列。方向设置为正向,确保左侧的值小于或等于右侧的值。请查看该链接以获取更多指导。

测试以下代码,看看它是否涵盖您的用例:

res = (pd.merge_asof(df1,df,
                     by='id',
                     left_on='join_date',
                     right_on='event_date',
                     direction='forward')
       .fillna(0)
       .drop('event_date',axis=1)
       .assign(has_tier_1 = lambda x: np.where(x.tier == 1, 1, 0),
               has_tier_2 = lambda x: np.where(x.tier == 2, 1, 0)
              )
       .sort_values('id')
      )
res


    id  join_date   stop_date   tier    has_tier_1  has_tier_2
0   233 2013-03-12  2015-04-01  1.0        1           0
2   233 2016-03-12  2017-04-01  0.0        0           0
1   235 2013-03-12  2016-04-01  2.0        0           1