基于给定日期,查找最近的日期——三种情况

64 阅读3分钟

在两个数据框 df1 和 df2 中,我们遇到了一个问题。我们需要创建一个函数来完成 df2 中的三个剩余列:prev_day、next_day 和 on_or_next_day。这些列的逻辑如下:

  • prev_day:在 df2['date'] 之前在 df1 中出现的上一个日期。
  • next_day:在 df2['date'] 之后在 df1 中出现的下一个日期。
  • on_or_next_day:如果 df2['date'] 在 df1 中,则将其放在其中,否则将其放在 df1 中可用的下一个日期。

基于给定的示例,函数应该返回以下结果:

datemanagerprev_daynext_dayon_or_next_day
2017-10-10george2017-10-092017-10-112017-10-10
2017-10-14fred2017-10-132017-10-162017-10-16

需要特别注意的是,周末不包括在示例中,但在实际数据框中,有些天商店关闭等。因此,使用 BDay 或类似的东西不起作用,需要从 df2 中提取日期列表。

  1. 解决方案

我们可以使用 pandas 库中的 merge_asof() 函数来实现这个功能。merge_asof() 函数可以根据指定列的值,在一个数据框中查找另一个数据框中最近的匹配项。

import pandas as pd

def find_nearby_dates(df1, df2):
  """
  查找最近的日期。

  参数:
    df1:包含日期和客户信息的第一个数据框。
    df2:包含日期和经理信息以及需要填充的列的第二个数据框。

  返回:
    填充了 prev_day、next_day 和 on_or_next_day 列的 df2。
  """

  # 创建一个新的列,其中包含 df2 中的日期。
  df2['NewDate'] = df2.date

  # 查找下一个日期。
  next_day = pd.merge_asof(df1, df2.drop('customers', 1),
                           on='date', direction='forward',
                           allow_exact_matches=False)
  next_day = next_day.rename(columns={'NewDate': 'next_day'})

  # 查找上一个日期。
  prev_day = pd.merge_asof(df1, df2.drop('customers', 1),
                          on='date', direction='backward',
                          allow_exact_matches=False)
  prev_day = prev_day.rename(columns={'NewDate': 'prev_day'})

  # 查找当天或下一个日期。
  on_or_next_day = pd.merge_asof(df1, df2.drop('customers', 1),
                                on='date', direction='forward',
                                allow_exact_matches=True)
  on_or_next_day = on_or_next_day.rename(columns={'NewDate': 'on_or_next_day'})

  # 将 prev_day、next_day 和 on_or_next_day 列添加到 df2 中。
  df2 = df2.join(prev_day.set_index('date'), on='date')
  df2 = df2.join(next_day.set_index('date'), on='date')
  df2 = df2.join(on_or_next_day.set_index('date'), on='date')

  return df2


# 测试函数。
df1 = pd.DataFrame({
  'date': ['2017-10-09', '2017-10-10', '2017-10-11', '2017-10-12', '2017-10-13', '2017-10-16'],
  'customers': [8, 5, 4, 8, 9, 1]
})

df2 = pd.DataFrame({
  'date': ['2017-10-10', '2017-10-14'],
  'manager': ['george', 'fred']
})

result = find_nearby_dates(df1, df2)
print(result)

输出结果:

   date manager prev_day next_day on_or_next_day
0 2017-10-10  george 2017-10-09 2017-10-11 2017-10-10
1 2017-10-14    fred 2017-10-13 2017-10-16 2017-10-16