【问题标题】:Check if date in one dataframe is between two dates in another dataframe, by group按组检查一个数据框中的日期是否介于另一个数据框中的两个日期之间
【发布时间】:2020-05-22 20:19:53
【问题描述】:

我有以下问题。我有一个数据框,其中包含每个组的开始日期和结束日期。 每个组可能有多个开始和结束日期,如下所示:

group   start_date    end_date
 1      2020-01-03    2020-03-03
 1      2020-05-03    2020-06-03
 2      2020-02-03    2020-06-03

还有另一个数据框,每个日期,每个组一行,如下所示:

group   date
 1     2020-01-03
 1     2020-02-03
 1     2020-03-03
 1     2020-04-03
 1     2020-05-03
 1     2020-06-03
 2     2020-02-03
 3     2020-03-03
 4     2020-04-03
      .
      .

所以我想以一种有效的方式创建一个列is_between,最好避免循环,所以我得到以下数据框

group   date          is_between
 1     2020-01-03        1
 1     2020-02-03        1
 1     2020-03-03        1
 1     2020-04-03        0
 1     2020-05-03        1
 1     2020-06-03        1
 2     2020-02-03        1
 3     2020-03-03        1
 4     2020-04-03        1
      .
      .

因此,当组的日​​期介于第一个数据帧中的日期之间时,它会得到 1。我猜groupbywherebetweenmap 的某种组合可能会做到这一点,但我没有找到正确的组合。有什么想法吗?

【问题讨论】:

  • 你的数据框有多少行?
  • 合并做条件?
  • 第一个大约70-80(每天更新),第二个,几千。这必须在 512mb RAM 虚拟机上运行,​​以及许多其他进程,因此效率非常重要
  • Merge 会为获得多个开始和结束日期的组带来重复项,这意味着必须按组和is_between 排序,然后是 drop_duplicates,这似乎不太有效,但是它会起作用,而且比我目前得到的要好。
  • 对于80 x 10k 数据,合并还不错。而且速度很快。

标签: python pandas date


【解决方案1】:

根据@YOBEN_S 和@Quang Hoang 的建议,我们做到了:

df = df.merge(dic_dates, how='left')
df['is_between'] = np.where(df.date.between(pd.to_datetime(df.start_date),
                                                                   pd.to_datetime(df.end_Date)),1, 0)
df = (df.sort_values(by=['group', 'date', 'is_between'])
            .drop_duplicates(subset=['group', 'date'], keep='last'))

【讨论】:

  • 你好胡安。我刚刚遇到了类似的问题。你能告诉你什么是df,你的例子中的dic_dates是什么>
【解决方案2】:

您可以尝试使用merge_asofby 组和on 日期和 start_date,然后检查日期小于 end_date 的位置,最后分配回原始 df2

ser = (pd.merge_asof(df2.reset_index() #for later index alignment
                        .sort_values('date'), 
                     df1.sort_values('start_date'), 
                     by='group', 
                     left_on='date', right_on='start_date', 
                     direction='backward')
         .assign(is_between=lambda x: x.date<=x.end_date)
         .set_index(['index'])['is_between']
        )

df2['is_between'] = ser.astype(int)

print (df2)
   group       date  is_between
0      1 2020-01-03           1
1      1 2020-02-03           1
2      1 2020-03-03           1
3      1 2020-04-03           0
4      1 2020-05-03           1
5      1 2020-06-03           1
6      2 2020-02-03           1
7      3 2020-03-03           0
8      4 2020-04-03           0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-26
    • 2021-10-18
    • 2021-08-23
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 2016-10-02
    • 2022-01-22
    相关资源
    最近更新 更多