Python pandas 两张表匹配查找最新日期

Python pandas two table match to find latest date

提问人:Elaine Yang 提问时间:3/8/2023 更新时间:3/8/2023 访问量:60

问:

我想在 Excel 中的 Vlookup 等熊猫中进行一些匹配。根据表1中的一些条件,找到表2中的最新日期:

表1:

Name  Threshold1   Threshold2
A     9            8
B     14           13

表2:

Date   Name   Value   
1/1    A      10
1/2    A      9
1/3    A      9
1/4    A      8
1/5    A      8
1/1    B      15
1/2    B      14
1/3    B      14
1/4    B      13
1/5    B      13

所需的表格如下所示:

Name  Threshold1   Threshold1_Date   Threshold2   Threshold2_Date
A     9            1/3               8            1/5
B     14           1/3               13           1/5

提前致谢!

Python Pandas DataFrame 匹配 查找

评论

0赞 Elaine Yang 3/8/2023
表 1 和 2 是 pandas 数据帧

答:

2赞 Scott Boston 3/8/2023 #1

这行得通吗?

(df_out := df1.melt('Name', value_name='Value')\
   .merge(df2, on=['Name', 'Value'])\
   .sort_values('Date')\
   .drop_duplicates(['Name', 'variable'], keep='last')\
   .set_index(['Name', 'variable'])\
   .unstack().sort_index(level=1, axis=1))\
.set_axis(df_out.columns.map('_'.join), axis=1).reset_index()

输出:

  Name Date_Threshold1  Value_Threshold1 Date_Threshold2  Value_Threshold2
0    A             1/3                 9             1/5                 8
1    B             1/3                14             1/5                13
3赞 Shubham Sharma 3/8/2023 #2

法典

# assuming dataframe is already sorted on `date`
# drop the duplicates per Name and Value keeping the max date
cols = ['Name', 'Value']
s = df2.drop_duplicates(cols, keep='last').set_index(cols)['Date']

# for each threshold column use multindex.map to substitute 
# values from df2 based on matching Name and Threshold value
for c in df1.filter(like='Threshold'):
    df1[c + '_date'] = df1.set_index(['Name', c]).index.map(s)

结果

  Name  Threshold1  Threshold2 Threshold1_date Threshold2_date
0    A           9           8             1/3             1/5
1    B          14          13             1/3             1/5

评论

0赞 Scott Boston 3/8/2023
很棒的解决方案。我太花哨了。:)
0赞 Shubham Sharma 3/8/2023
谢谢斯科特..顺便说一句,为什么要删除解决方案..对我来说看起来很酷:-)
1赞 Elaine Yang 3/8/2023
谢谢舒巴姆。顺便说一句,我没有机会阅读斯科特的解决方案>_<
0赞 constantstranger 3/8/2023 #3

以下是解决您的问题的方法:

latestDtByNameVal = df2.groupby(['Name','Value']).last()
resCols = (y for x in df1.columns if x != 'Name' for y in [x, f'{x}_Date'])
res = df1.assign(**( df1
    .set_index('Name')
    .pipe(lambda d:
        {f'{col}_Date': d[[col]]
            .rename(columns={col:'Value'})
            .set_index('Value', append=True)
            .pipe(lambda d2: latestDtByNameVal.Date[d2.index].to_numpy()) 
        for col in d.columns}) ))[resCols]

解释:

  • 用于获取 ,这是 df2 中按唯一对索引的最新日期groupby().last()latestDtByNameValName, Value
  • 在生成器中准备结果列顺序,如问题中所示resColsThreshold1, Threshold1_Date, ...
  • 要增加 df1 的列以包含阈值日期结果作为标签以 结尾的列,请将字典映射传递到相应对索引处的行值_Dateassign()<threshColName>_DateDatelatestDtByNameValName, Value
  • 使用 按所需顺序排列列。resCols

输出:

  Name  Threshold1 Threshold1_Date  Threshold2 Threshold2_Date
0    A           9             1/3           8             1/5
1    B          14             1/3          13             1/5