按最接近的较低日期或相等日期合并数据帧

Merge dataframes by the nearest lower or equal date

提问人:Aleksandra 提问时间:11/17/2023 最后编辑:petezurichAleksandra 更新时间:11/17/2023 访问量:41

问:

我有两个数据框:

df1 = pd.DataFrame({'ID':['A', 'A', 'B', 'B'], 
    'Date':['31.08.2023', '12.09.2023', '13.09.2023', '20.08.2023']})

df2 = pd.DataFrame({'ID':['A', 'A', 'A', 'B', 'B'], 
        'Date':['30.08.2023', '14.09.2023', '10.09.2023', '28.09.2023', '19.08.2023']})

我想向 df1 添加两个新列,每个 ID 中都有最接近的上下日期,因此此示例中的期望输出将如下所示:

编号 日期 DATE_UP DATE_DOWN
一个 31.08.2023 10.09.2023 30.08.2023
一个 12.09.2023 14.09.2023 10.09.2023
B 13.09.2023 28.09.2023 19.08.2023
B 20.08.2023 28.09.2023 19.08.2023

我知道有一个 pandas 函数 merge_asof(),但它仅适用于最近的合并。 对于如何有效地做到这一点的任何想法,我都会非常满意。

蟒蛇 熊猫 numpy

评论


答:

2赞 Panda Kim 11/17/2023 #1

法典

您可以通过以下方式解决它。merge_asof 不仅适用于最近的合并。即使最近不是默认值,默认值是向后。merge_asof


首先制作名为“Date1”的日期时间列并排序

df1['Date1'] = pd.to_datetime(df1['Date'], dayfirst=True)
df1 = df1.sort_values('Date1')
df2['Date1'] = pd.to_datetime(df2['Date'], dayfirst=True)
df2 = df2.sort_values('Date1')

DF1:

    ID  Date        Date1
3   B   20.08.2023  2023-08-20
0   A   31.08.2023  2023-08-31
1   A   12.09.2023  2023-09-12
2   B   13.09.2023  2023-09-13

DF2:

    ID  Date        Date1
4   B   19.08.2023  2023-08-19
0   A   30.08.2023  2023-08-30
2   A   10.09.2023  2023-09-10
1   A   14.09.2023  2023-09-14
3   B   28.09.2023  2023-09-28

接下来使用前进和后退(默认)merge_asof

tmp = pd.merge_asof(df1.reset_index(), df2, on='Date1', by='ID', 
                    direction='forward', suffixes=['', '_up'])
out = pd.merge_asof(tmp, df2, on='Date1', by='ID', suffixes=['', '_down'])\
        .drop('Date1', axis=1).set_index('index').sort_index().rename_axis('')

外:

    ID  Date        Date_up     Date_down
0   A   31.08.2023  10.09.2023  30.08.2023
1   A   12.09.2023  14.09.2023  10.09.2023
2   B   13.09.2023  28.09.2023  19.08.2023
3   B   20.08.2023  28.09.2023  19.08.2023
0赞 Kamil 11/17/2023 #2

创建数据帧

import pandas as pd

df1 = pd.DataFrame({
    'ID': ['A', 'A', 'B', 'B'],
    'Date': ['31.08.2023', '12.09.2023', '13.09.2023', '20.08.2023']
})

df2 = pd.DataFrame({
    'ID': ['A', 'A', 'A', 'B', 'B'],
    'Date': ['30.08.2023', '14.09.2023', '10.09.2023', '28.09.2023', '19.08.2023']
})

将“日期”列转换为日期时间

df1['Date'] = pd.to_datetime(df1['Date'], dayfirst=True)
df2['Date'] = pd.to_datetime(df2['Date'], dayfirst=True)

按“ID”和“Date”对数据帧进行排序

df1 = df1.sort_values(by=['ID', 'Date'])
df2 = df2.sort_values(by=['ID', 'Date'])

查找最近的较高日期 (DATE_UP)

df1['DATE_UP'] = df1.apply(lambda row: df2[(df2['ID'] == row['ID']) & (df2['Date'] > row['Date'])]['Date'].min(), axis=1)

查找最近的较低日期 (DATE_DOWN)

df1['DATE_DOWN'] = df1.apply(lambda row: df2[(df2['ID'] == row['ID']) & (df2['Date'] < row['Date'])]['Date'].max(), axis=1)

将 'Date', 'DATE_UP', 'DATE_DOWN' 转换回原始字符串格式

df1['Date'] = df1['Date'].dt.strftime('%d.%m.%Y')
df1['DATE_UP'] = df1['DATE_UP'].dt.strftime('%d.%m.%Y')
df1['DATE_DOWN'] = df1['DATE_DOWN'].dt.strftime('%d.%m.%Y')