如何在非唯一列中按日期对pandas DataFrame条目进行分组


80

熊猫DataFrame包含名为的列"date",其中包含非唯一datetime值。我可以使用以下方法将该行中的行分组:

data.groupby(data['date'])

但是,这会将数据按datetime值分割。我想按“日期”列中存储的年份对这些数据进行分组。此页面显示了在使用时间戳作为索引的情况下如何按年份分组,在我的情况下情况并非如此。

如何实现此分组?


对于2017年以上来这里的人们,有几种新方法可以对特定时间进行分组。请在下方查看此答案
Ted Petrou

Answers:


88

我正在使用熊猫0.16.2。这在我的大型数据集上具有更好的性能:

data.groupby(data.date.dt.year)

使用dt选项和玩弄weekofyeardayofweek等变得更加容易。


同意,这似乎是访问系列日期属性的一种常见方式。
Dan Nguyen

73

ecatmur的解决方案可以正常工作。不过,这将在大型数据集上获得更好的性能:

data.groupby(data['date'].map(lambda x: x.year))

9
为什么使用地图而不是应用?
2015年

1
map与仅使用相比,Afaik在应用任意函数时通常具有一些良好的效率品质apply
Coolio2654 '18

24

使用样本数据集可能更容易解释。

创建样本数据

假设我们只有一列“时间戳记”,date另一列是我们希望对进行聚合的a

df = pd.DataFrame({'date':pd.DatetimeIndex(['2012-1-1', '2012-6-1', '2015-1-1', '2015-2-1', '2015-3-1']),
                   'a':[9,5,1,2,3]}, columns=['date', 'a'])

df

        date  a
0 2012-01-01  9
1 2012-06-01  5
2 2015-01-01  1
3 2015-02-01  2
4 2015-03-01  3

有几种按年分组的方法

  • 将dt访问器与year属性一起使用
  • 放入date索引并使用匿名功能访问年份
  • 使用resample方法
  • 转换为熊猫时期

.dt具有year属性的访问者

当您有pandas Timestamps的列(而不是索引)时,可以使用访问器访问更多其他属性和方法dt。例如:

df['date'].dt.year

0    2012
1    2012
2    2015
3    2015
4    2015
Name: date, dtype: int64

我们可以使用它来形成我们的组并计算特定列上的一些聚合:

df.groupby(df['date'].dt.year)['a'].agg(['sum', 'mean', 'max'])

      sum  mean  max
date                
2012   14     7    9
2015    6     2    3

将日期放入索引并使用匿名函数访问年份

如果将日期列设置为索引,则它将变为DateTimeIndex,其属性和方法与dt访问器提供的常规列相同

df1 = df.set_index('date')
df1.index.year

Int64Index([2012, 2012, 2015, 2015, 2015], dtype='int64', name='date')

有趣的是,在使用groupby方法时,可以向其传递一个函数。该函数将隐式传递给DataFrame的索引。因此,我们可以从上面获得以下相同的结果:

df1.groupby(lambda x: x.year)['a'].agg(['sum', 'mean', 'max'])

      sum  mean  max
2012   14     7    9
2015    6     2    3

使用resample方法

如果日期列不在索引中,则必须使用on参数指定该列。您还需要将偏移别名指定为字符串。

df.resample('AS', on='date')['a'].agg(['sum', 'mean', 'max'])

             sum  mean  max
date                       
2012-01-01  14.0   7.0  9.0
2013-01-01   NaN   NaN  NaN
2014-01-01   NaN   NaN  NaN
2015-01-01   6.0   2.0  3.0

转换为熊猫时期

您还可以将日期列转换为熊猫Period对象。我们必须将offset别名作为字符串传递,以确定Period的长度。

df['date'].dt.to_period('A')

0   2012
1   2012
2   2015
3   2015
4   2015
Name: date, dtype: object

然后我们可以将其作为一个组

df.groupby(df['date'].dt.to_period('Y'))['a'].agg(['sum', 'mean', 'max'])


      sum  mean  max
2012   14     7    9
2015    6     2    3

在您使用的最后一种方法中to_period('A'),(A)是什么意思?
Shiv_90 '18

2
@ Shiv_90'A'是时间偏移量别名:pandas.pydata.org/pandas-docs/stable/…–
ptim

如果还需要保存一个单独的“日期”列,您会建议使用哪种方法?例如,如果我运行简单.dt.year方法并将其保存在新的数据框中,则日期将另存为索引,如果说我需要绘制数据,这将成为问题,因为“日期”列并不真正存在,而只有三个在.agg()
Shiv_90 '18

13

这应该工作:

data.groupby(lambda x: data['date'][x].year)

0

这也将工作

data.groupby(data['date'].dt.year)


应该可以工作,但是执行时会输出对象在内存中的位置,但没有实际输出。<pandas.core.groupby.DataFrameGroupBy object at 0x10d7f6438>是我执行时得到的。
Shiv_90 '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.