根据开始和结束日期对时间序列数据进行分组

时间:2018-12-26 09:37:40

标签: python pandas

我有每年一次体育比赛的时间序列数据,以及每场比赛的举行日期。我想按游戏的季节(年)对游戏进行分组。每个季节都从8月开始,到7月结束。

我将如何按季节对游戏进行分组,例如- 季节(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))

但是我宁愿选择更优雅,更包含时间序列数据的东西,所以我将继续公开这个问题。

4 个答案:

答案 0 :(得分:2)

成功的关键是针对您的情况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')
# Groupping
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日。

您可以随心所欲地与小组合作。

答案 1 :(得分:1)

使用-

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

答案 2 :(得分:1)

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月结束。

答案 3 :(得分:0)

您可以建立一个季节专栏并以此分组。在下面的代码中,我使用pandas.DateOffset()将所有日期都移回了7个月,因此,八月份发生的游戏看起来就像在一月份发生的那样,将季节年份与日历年份保持一致。在那之后,构建季节字符串非常简单。

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()