【问题标题】:How to group pandas dataframe by custom overlapping periods?如何按自定义重叠时段对熊猫数据框进行分组?
【发布时间】:2021-03-14 01:01:54
【问题描述】:

假设我有一个列表列表,其中每个嵌套列表都有两个值:一个范围的开始日期和一个范围的结束日期。所以是这样的:

ranges_list = [
    ['2020-03-12', '2020-06-12'],
    ['2020-03-13', '2020-06-13'],
    ['2020-03-14', '2020-06-14']
]

这代表 3 个范围:

  1. 2020 年 3 月 12 日 - 2020 年 6 月 12 日
  2. 2020 年 3 月 13 日 - 2020 年 6 月 13 日
  3. 2020 年 3 月 14 日 - 2020 年 6 月 14 日

假设我还有一些数据框 d 有多个列,其中一个是名为 'occurence_date' 的列,其中包含日期时间。

假设数据框 d 看起来像:

ID      LinkID   PC    occurence_date
10R46   R*1005   8017  2020-03-12
10R46   R*10335  5019  2020-04-15
100R91  R*1005   8017  2020-04-15
10R91   R*243    8870  2020-06-14

我想在ranges_list 中指定的范围内使用occurence_date 列对数据框d 进行分组

比如:

grouped = d.groupby('occurence_date', ranges=ranges_list)

显然,这个 groupby 代码不正确,但有助于实现我想做的事情。

最后,分组对象应该有 3 个不同的组,如下所示:

group: ('2020-03-12', '2020-06-12')
ID      LinkID   PC    occurence_date
10R46   R*1005   8017  2020-03-12
10R46   R*10335  5019  2020-04-15
100R91  R*1005   8017  2020-04-15

group: ('2020-03-13', '2020-06-13')
ID      LinkID   PC    occurence_date
10R46   R*10335  5019  2020-04-15
100R91  R*1005   8017  2020-04-15

group: ('2020-03-14', '2020-06-14')
ID      LinkID   PC    occurence_date
10R46   R*10335  5019  2020-04-15
100R91  R*1005   8017  2020-04-15
10R91   R*243    8870  2020-06-14

我怎样才能做到这一点?

【问题讨论】:

    标签: python pandas group-by pandas-groupby period


    【解决方案1】:

    以下交互式会话展示了如何获得必要的数据以根据需要将记录组合​​在一起。可能有更有效的方法,因为这将遍历 len(d) * len(dranges),但如果您没有大量数据,这是一个简单的解决方案。

    >>> d
           ID   LinkID    PC occurence_date
    0   10R46   R*1005  8017     2020-03-12
    1   10R46  R*10335  5019     2020-04-15
    2  100R91   R*1005  8017     2020-04-15
    3   10R91    R*243  8870     2020-06-14
    
    >>> dranges
                0           1
    0  2020-03-12  2020-06-12
    1  2020-03-13  2020-06-13
    2  2020-03-14  2020-06-14
    
    >>> d['overlaps'] = d.apply(lambda row: [f'{dr[0]} to {dr[1]}' 
                                             for _, dr in dranges.iterrows() 
                                             if row['occurence_date'] >= dr[0] 
                                             and row['occurence_date'] <= dr[1]]
                               , axis=1)
    
    >>> d.explode('overlaps').sort_values('overlaps')
           ID   LinkID    PC occurence_date                  overlaps
    0   10R46   R*1005  8017     2020-03-12  2020-03-12 to 2020-06-12
    1   10R46  R*10335  5019     2020-04-15  2020-03-12 to 2020-06-12
    2  100R91   R*1005  8017     2020-04-15  2020-03-12 to 2020-06-12
    1   10R46  R*10335  5019     2020-04-15  2020-03-13 to 2020-06-13
    2  100R91   R*1005  8017     2020-04-15  2020-03-13 to 2020-06-13
    1   10R46  R*10335  5019     2020-04-15  2020-03-14 to 2020-06-14
    2  100R91   R*1005  8017     2020-04-15  2020-03-14 to 2020-06-14
    3   10R91    R*243  8870     2020-06-14  2020-03-14 to 2020-06-14
    

    【讨论】:

      【解决方案2】:

      您可以按pd.IntervalIndex分组:

      ranges_list = [
          (pd.Timestamp('2020-03-12'), pd.Timestamp('2020-06-12')),
          (pd.Timestamp('2020-03-13'), pd.Timestamp('2020-06-13')),
          (pd.Timestamp('2020-03-14'), pd.Timestamp('2020-06-14'))
      ]
      
      idx = pd.IntervalIndex.from_tuples(ranges_list, closed='both')
      
      def in_ranges(x, bins):
          rv = []
          for b in bins:
              if x in b:
                  rv.append(b)
          return rv
      
      df['groups'] = df['occurence_date'].apply(lambda x: in_ranges(x, idx))
      
      for g in df.explode('groups').groupby('groups'):
          print(g[0])
          print('-' * 80)
          print(g[1][['ID', 'LinkID', 'PC', 'occurence_date']])
          print()
      

      打印:

      [2020-03-12, 2020-06-12]
      --------------------------------------------------------------------------------
             ID   LinkID    PC occurence_date
      0   10R46   R*1005  8017     2020-03-12
      1   10R46  R*10335  5019     2020-04-15
      2  100R91   R*1005  8017     2020-04-15
      
      [2020-03-13, 2020-06-13]
      --------------------------------------------------------------------------------
             ID   LinkID    PC occurence_date
      1   10R46  R*10335  5019     2020-04-15
      2  100R91   R*1005  8017     2020-04-15
      
      [2020-03-14, 2020-06-14]
      --------------------------------------------------------------------------------
             ID   LinkID    PC occurence_date
      1   10R46  R*10335  5019     2020-04-15
      2  100R91   R*1005  8017     2020-04-15
      3   10R91    R*243  8870     2020-06-14
      

      【讨论】:

        猜你喜欢
        • 2017-07-04
        • 2019-07-10
        • 1970-01-01
        • 2013-02-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-17
        • 2023-03-16
        相关资源
        最近更新 更多