【问题标题】:Cannot use pandas.merge_asof with multiple columns不能对多列使用 pandas.merge_asof
【发布时间】:2023-01-19 01:16:57
【问题描述】:

我正在尝试合并两个 pandas 数据框,每个数据框包含两个字符串列和一个日期列。

df1
a    b      date
100  200    2022-01-03
100  200    2022-01-04
101  200    2022-01-05
101  200    2022-01-06
101  200    2022-01-07

df2
a    b      date
100  200    2022-01-04
100  200    2022-01-06
101  200    2022-01-03
101  200    2022-01-06
101  200    2022-01-09

目标是将它们合并到 a、b、日期并取最近的日期(正向)。 期望的输出:

df
a    b      date_x      date_y
100  200    2022-01-03  2022-01-04
100  200    2022-01-04  2022-01-04
101  200    2022-01-05  2022-01-06 (not 2022-01-03 because it is behind not forward)
101  200    2022-01-06  2022-01-06
101  200    2022-01-07  2022-01-09

【问题讨论】:

  • 必须 a,b 匹配吗?
  • 是的; a,b 必须匹配
  • 告诉我我的解决方案是否有效:)

标签: python pandas date join merge


【解决方案1】:

我们可以在ab 上合并,根据date_ydate_x 之间的最小差异进行过滤,同时考虑到前进方向

new_df = df1.merge(df2, on=['a', 'b'], how='inner')
            .assign(diff_date=lambda df: df['date_y']
                        .sub(df['date_x'])
                        .where(lambda x: df['date_y'].ge(df['date_x'])), 
                    mask=lambda df: df['diff_date']
                        .eq(df.groupby(['a', 'b', 'date_x'])['diff_date']
                        .transform('min')))
            .loc[lambda df: df['mask']]
            .drop(['diff_date', 'mask'], axis=1)
print(new_df)


    a    b     date_x     date_y
0   100  200 2022-01-03 2022-01-04
2   100  200 2022-01-04 2022-01-04
5   101  200 2022-01-05 2022-01-06
8   101  200 2022-01-06 2022-01-06
12  101  200 2022-01-07 2022-01-09

【讨论】:

  • 这是一个很好的解决方案。我正在寻找的不是立即合并 df1 和 df2。在这里尝试使用 pd.merge_asof。如果我们无法解决,我会接受您的解决方案 :)
【解决方案2】:

你也可以试试

# merge on a,b and sort based on date
m = df1.merge(df2, on=['a', 'b'], how='left').sort_values(['date_x', 'date_y'])
# only keep dates that are <= df2 date
df = m[m['date_x'] <= m['date_y']]
# drop duplicates and filter
final_df = df.loc[df[['a', 'b', 'date_x']].drop_duplicates(keep='first').index]

      a    b     date_x     date_y
0   100  200 2022-01-03 2022-01-04
2   100  200 2022-01-04 2022-01-04
5   101  200 2022-01-05 2022-01-06
8   101  200 2022-01-06 2022-01-06
12  101  200 2022-01-07 2022-01-09

【讨论】:

  • drop_duplicates 在这里很好
  • 谢谢,但我认为这在计算上有点昂贵,尤其是当我的 df2 太大时。我们可以使用 pd.merge_asof 吗?
  • @sakalansaka 你为什么这么认为,sort_values?我真的想不出使用merge_asof 的方法,因为您想要 a 和 b 的精确匹配,但需要日期的正向匹配。
【解决方案3】:
import pandas as pd

df1 = pd.DataFrame({'a': ['100', '100', '101', '101', '101'],
                    'b': ['200', '200', '200', '200', '200'],
                    'date': ['2022-01-03', '2022-01-04', '2022-01-05', '2022-01-06', '2022-01-07']})

df2 = pd.DataFrame({'a': ['100', '100', '101', '101', '101'],
                    'b': ['200', '200', '200', '200', '200'],
                    'date': ['2022-01-04', '2022-01-06', '2022-01-03', '2022-01-06', '2022-01-09']})
  
df3 = pd.merge(df1,df2,how='left',left_on=['a','b'],right_on=['b','a']).drop(['a_y','b_y'], axis=1) 
df3['date_y'] = df2['date']

【讨论】:

    猜你喜欢
    • 2019-11-25
    • 2021-02-19
    • 2019-05-15
    • 2022-08-11
    • 2022-07-25
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多