【问题标题】:Left join DataFrame where the Date in the left DataFrame is contained in the range of Dates based around a Date in the right DataFrame左连接 DataFrame,其中左侧 DataFrame 中的 Date 包含在基于右侧 DataFrame 中的 Date 的 Dates 范围内
【发布时间】:2019-09-03 05:30:22
【问题描述】:
import pandas as pd
df_A = pd.DataFrame({'Team_A': ['Cowboys', 'Giants'], 'Team_B': ['Eagles', 'Redskins'], 'Start':['2017-11-09','2017-09-10']})
df_B = pd.DataFrame({'Team_A': ['Cowboys', 'Cowboys', 'Giants'], 'Team_B': ['Eagles', 'Eagles','Redskins'], 'Start':['2017-11-09','2017-11-11','2017-09-10']})

df_A['Start'] = pd.to_datetime(df_A.Start)
df_B['Start'] = pd.to_datetime(df_B.Start)

我想留在 df A 上。问题是,比赛可能会在 df_B 中重复,通常日期略有不同,距正确日期(df A 中列出的日期)不超过 +- 4 天。在所示示例中,df A 中的第一个游戏显示了两次:第一次显示正确的日期,第二次显示错误的日期。第一个日期不一定是正确的。也可能会显示多个错误日期,因此游戏可能会出现两次以上。另请注意,上面的示例在实际问题中进行了简化,还有其他几列可能匹配也可能不匹配。另一个关键点是,这些团队将在真正的问题中再次出现几次,但日期要远超过 +- 4 天。

df_merge = pd.merge(df_A, df_B, on=['Team_A', 'Team_B', 'Start'], how='left')

这与我想要的很接近,但只提供了开始日期完全匹配的游戏。我还想要在开始日期 +- 4 天内的游戏。

Merging two dataframes based on a date between two other dates without a common column

这解决了一个类似的问题,但在我的情况下,每个 DataFrame 中的行数不同,所以它对我不起作用。

我也试过这个,但无法让它为我工作:

How to join two table in pandas based on time with delay

我也试过了:

a = df_A['Start'] - pd.Timedelta(4, unit='d')
b = df_A['Start'] + pd.Timedelta(4, unit='d')
df = db_B[db_B['Start'].between(a, b, inclusive=False)]

但这同样不起作用,因为每个 DataFrame 中的行数不同。

【问题讨论】:

  • 您介意添加预期的输出吗?
  • 为了得到我想要的输出,需要进行一些排序,但没有什么太大的挑战。

标签: python pandas


【解决方案1】:

IIUC 你宁愿使用outer 合并,如下例所示

import pandas as pd
df_A = pd.DataFrame({'Team_A': ['Cowboys', 'Giants'], 'Team_B': ['Eagles', 'Redskins'], 'Start':['2017-11-09','2017-09-10']})
df_B = pd.DataFrame({'Team_A': ['Cowboys', 'Cowboys', 'Giants'], 'Team_B': ['Eagles', 'Eagles','Redskins'], 'Start':['2017-11-09','2017-11-11','2017-09-10']})

df_A['Start'] = pd.to_datetime(df_A.Start)
df_B['Start'] = pd.to_datetime(df_B.Start)
# +/- 4 days
df_A["lower"] = df_A["Start"]- pd.Timedelta(4, unit='d')
df_A["upper"] = df_A["Start"] + pd.Timedelta(4, unit='d')
# Get rid of Start col
df_A = df_A.drop("Start", axis=1)
# outer merge on Team_A, Team_B only
df = pd.merge(df_A, df_B, on=['Team_A', 'Team_B'], how='outer')
# filter
df = df[df["Start"].between(df["lower"], df["upper"])].reset_index(drop=True)

如果您的数据框很大,您可以考虑使用dask

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-30
    • 1970-01-01
    • 2022-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-29
    • 1970-01-01
    相关资源
    最近更新 更多