【问题标题】:How to group by consecutive dates when you have several groups?当您有多个组时,如何按连续日期分组?
【发布时间】:2020-10-12 23:29:15
【问题描述】:

我以为这会非常直接,但我被卡住了。我尝试以几种不同的方式进行分组,以及创建一个 .diff() 列并循环遍历唯一名称,但我仍然无法让它工作。

我得到的最多的是第一个“约会三明治”,但其余的都被忽略了。

基本上我有一个看起来像这样的表:

Name
Bob Smith   6/1/2020
Bob Smith   6/2/2020
Bob Smith   6/3/2020
Bob Smith   6/10/2020
Bob Smith   6/11/2020
Bob Smith   6/12/2020
Bob Smith   6/13/2020
Joe Doe     5/20/2020
Joe Doe     5/21/2020
Joe Doe     5/22/2020
Joe Doe     5/23/2020
Joe Doe     6/4/2020
Joe Doe     6/5/2020
Joe Doe     6/6/2020
Mark Scott  6/18/2020
Mark Scott  6/19/2020

我想提取每个连续日期条纹的开始日期和结束日期:

Name:           From:        To:
Bob Smith       6/1/2020     6/3/2020
Bob Smith       6/10/2020    6/13/2020
Joe Doe         5/20/2020    5/23/2020
Joe Doe         6/4/2020     6/6/2020
Mark Scott      6/18/2020    6/19/2020

提前感谢您的帮助!

【问题讨论】:

    标签: python pandas datetime group-by


    【解决方案1】:

    另一种不使用 groupby 的方法。使用掩码获取Namedates的第一个和最后一个日期并通过ndarray分配

    df.dates = pd.to_datetime(df.dates)
    m = df.dates.diff().ne(pd.Timedelta(days=1))
    df_final = df[m].assign(To_dates=df.loc[~m.cumsum().duplicated(keep='last'), 'dates']
                                       .values)
    
    Out[111]:
              Name      dates   To_dates
    0    Bob Smith 2020-06-01 2020-06-03
    3    Bob Smith 2020-06-10 2020-06-13
    7      Joe Doe 2020-05-20 2020-05-23
    11     Joe Doe 2020-06-04 2020-06-06
    14  Mark Scott 2020-06-18 2020-06-19
    

    【讨论】:

    • 感谢您的回答。我试图通过使用 .diff() 函数创建一个新列来做一个掩码。我通过循环按照“名称”完成了它,然后 .bfill() 清除了我每人获得的第一个 NaN。但是,我没有想过以您的方式定义 To Dates。对我来说还有很多东西要学,谢谢!
    【解决方案2】:

    我会将groupbydiffcumsumpd.NamedAgg 一起使用:

    df['Date'] = pd.to_datetime(df['Date'])
    grp = df['Date'].diff().ne(pd.Timedelta(days=1)).cumsum()
    df.groupby(['Name', grp])[['Name', 'Date']].agg(Name=('Name','first'),
                                          From=('Date','min'),
                                          To=('Date','max')).reset_index(drop=True)
    

    输出:

             Name       From         To
    0   Bob Smith 2020-06-01 2020-06-03
    1   Bob Smith 2020-06-10 2020-06-13
    2     Joe Doe 2020-05-20 2020-05-23
    3     Joe Doe 2020-06-04 2020-06-06
    4  Mark Scott 2020-06-18 2020-06-19
    

    【讨论】:

    • 非常感谢,这就像一个魅力。 Groupby 字符串会变得复杂!
    【解决方案3】:

    您需要使用 diffcumsum 创建子组密钥,然后使用 first + last 执行 agg

    df=pd.to_datetime(df).reset_index()
    m=df.date.diff().dt.days.ne(1).cumsum()
    s=df.groupby([df.Name,m]).date.agg(['first','last']).reset_index(level=1,drop=True)
    s
    
                   first       last
    Name                           
    BobSmith  2020-06-01 2020-06-03
    BobSmith  2020-06-10 2020-06-13
    JoeDoe    2020-05-20 2020-05-23
    JoeDoe    2020-06-04 2020-06-06
    MarkScott 2020-06-18 2020-06-19
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多