【问题标题】:grouping time-series data based on starting and ending date根据开始和结束日期对时间序列数据进行分组
【发布时间】:2018-12-26 09:37:39
【问题描述】:

我有一年一度的体育赛事的时间序列数据,包括每场比赛的日期。我想按他们参加的赛季(年份)对比赛进行分组。每个赛季从八月开始,到下一年的七月结束。

我将如何按赛季对比赛进行分组,例如 - 季节(2016-2017),季节(2017-2018)等等。

This Answer 涉及 df.resample() 可能是相关的,但我不知道该怎么做。

这是日期列的样子:

DATE
26/09/09
04/10/09
17/10/09
25/10/09
31/10/09
  ...   
29/09/18
07/10/18
28/10/18
03/11/18

我想按季节分组,以便对聚合数据执行可视化操作。

更新:目前我的解决方案是将数据框分成 32 组,因为我知道每个赛季有 32 场比赛。这是我使用的代码:

split_df = np.array_split(df, np.arange(0, len(df),32))

但我更喜欢更优雅、更包含时间序列数据的东西,所以我会保持这个问题的开放性。

【问题讨论】:

  • 你能给我们一些(样本)数据吗?

标签: python pandas


【解决方案1】:

成功的关键是正确的分组,在你的情况下是pd.Grouper(key='DATA', freq='AS-AUG')。

请注意,freq='AS-AUG' 声明您的组应该从 每年八月。

看下面的脚本:

import pandas as pd

# Source columns
dates = [ '01/04/09', '31/07/09', '01/08/09', '26/09/09', '04/10/09', '17/12/09', 
    '25/01/10', '20/04/10', '31/07/10', '01/08/10', '28/10/10', '03/11/10',
    '25/12/10', '20/04/11', '31/07/11' ]
scores_x = np.random.randint(0, 20, len(dates))
scores_y = np.random.randint(0, 20, len(dates))
# Source DataFrame
df = pd.DataFrame({'DATA': dates, 'SCORE_X': scores_x, 'SCORE_Y': scores_y})
# Convert string date to datetime
df.DATA = pd.to_datetime(df.DATA, format='%d/%m/%y')
# Grouping
gr = df.groupby(pd.Grouper(key='DATA', freq='AS-AUG'))

如果打印结果:

for name, group in gr:
    print()
    print(name)
    print(group)

你会得到:

2008-08-01 00:00:00
        DATA  SCORE_X  SCORE_Y
0 2009-04-01       16       11
1 2009-07-31       10        7

2009-08-01 00:00:00
        DATA  SCORE_X  SCORE_Y
2 2009-08-01       19        6
3 2009-09-26       14        5
4 2009-10-04        8       11
5 2009-12-17       12       19
6 2010-01-25        0        0
7 2010-04-20       17        6
8 2010-07-31       18        2

2010-08-01 00:00:00
         DATA  SCORE_X  SCORE_Y
9  2010-08-01       15       18
10 2010-10-28        2        4
11 2010-11-03        8       16
12 2010-12-25       13        1
13 2011-04-20       19        7
14 2011-07-31        8        3

如您所见,每组仅在 8 月 1 日开始,并于 8 月 1 日结束 7 月 31 日。

您可以随心所欲地对您的小组做任何事情。

【讨论】:

    【解决方案2】:

    使用 -

    df.groupby(df['DATE'].dt.year).count()
    

    输出

        DATE
    DATE    
    2009    5
    2018    4
    

    自定义季节分组

    min_year = df['DATE'].dt.year.min()
    max_year = df['DATE'].dt.year.max()
    rng = pd.date_range(start='{}-07'.format(min_year), end='{}-08'.format(max_year), freq='12M').to_series()
    df.groupby(pd.cut(df['DATE'], rng)).count()
    

    输出

        DATE
    DATE    
    (2009-07-31, 2010-07-31]    3
    (2010-07-31, 2011-07-31]    0
    (2011-07-31, 2012-07-31]    0
    (2012-07-31, 2013-07-31]    0
    (2013-07-31, 2014-07-31]    0
    (2014-07-31, 2015-07-31]    0
    (2015-07-31, 2016-07-31]    0
    (2016-07-31, 2017-07-31]    0
    (2017-07-31, 2018-07-31]    1
    

    【讨论】:

    • 题中提到赛季8月开始,7月结束
    • 所以 1 赛季将有一半的比赛在一年内,另一半在下一个.. 所以那个赛季的比赛将在 2009 年和 2010 年。下个赛季将是 2010 年和2011. 我猜这不会起作用。
    【解决方案3】:

    Resampling 使用 'A-JUL' 作为 anchored offset alias 应该可以解决问题:

    >>> df
                SAMPLE
    DATE              
    2009-01-30       1
    2009-07-10       4
    2009-11-20       3
    2010-01-01       5
    2010-05-13       1
    2010-08-01       1
    >>> df.resample('A-JUL').sum()
                SAMPLE
    DATE              
    2009-07-31       5
    2010-07-31       9
    2011-07-31       1
    

    A表示每年间隔,-JUL表示7月结束。

    【讨论】:

      【解决方案4】:

      您可以建立一个季节列并以此为基础进行分组。在下面的代码中,我使用pandas.DateOffset() 将所有日期向后移动了 7 个月,因此发生在 8 月的游戏看起来就像发生在 1 月,以使赛季年份与日历年保持一致。之后构建季节字符串就相当简单了。

      import pandas as pd
      from datetime import date
      
      dates = pd.date_range(date(2009, 8, 1), date(2018, 7, 30), freq='17d')
      df = pd.DataFrame(dates, columns=['date'])
      
      # copy the date column to a separate dataframe to do the work
      df_tmp = df[['date']]
      df_tmp['season_start_year'] = (df_tmp['date'] - pd.DateOffset(months=7)).dt.year
      df_tmp['season_end_year'] = df_tmp['season_start_year'] + 1
      df_tmp['season'] = df_tmp['season_start_year'].map(str) + '-' + df_tmp['season_end_year'].map(str)
      
      # copy season column to the main dataframe
      df['season'] = df_tmp['season']
      
      df.groupby('season').count()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-26
        相关资源
        最近更新 更多