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

Bor*_*lik 68 python pandas

Pandas DataFrame包含名为"date"包含非唯一datetime值的列.我可以使用以下方法对此帧中的行进行分组:

data.groupby(data['date'])
Run Code Online (Sandbox Code Playgroud)

但是,这会按datetime值拆分数据.我想按照"日期"列中存储的年份对这些数据进行分组.此页面显示如何在时间戳用作索引的情况下按年分组,在我的情况下不是这样.

我如何实现这种分组?

Wes*_*ney 70

ecatmur的解决方案将正常工作.不过,这对大型数据集的性能会更好:

data.groupby(data['date'].map(lambda x: x.year))
Run Code Online (Sandbox Code Playgroud)

  • 为什么地图而不是申请? (9认同)

DAC*_*ACW 70

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

data.groupby(data.date.dt.year)
Run Code Online (Sandbox Code Playgroud)

使用dt选项和玩弄weekofyear,dayofweek等变得更加容易.


Ted*_*rou 17

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

创建样本数据

假设我们有一列Timestamps,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
Run Code Online (Sandbox Code Playgroud)

有几种方法可以按年分组

  • 使用带year属性的dt访问器
  • 放入date索引并使用匿名函数访问年份
  • 使用resample方法
  • 转换为pandas Period

.dtyear财产的存取器

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

df['date'].dt.year

0    2012
1    2012
2    2015
3    2015
4    2015
Name: date, dtype: int64
Run Code Online (Sandbox Code Playgroud)

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

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

      sum  mean  max
date                
2012   14     7    9
2015    6     2    3
Run Code Online (Sandbox Code Playgroud)

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

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

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

Int64Index([2012, 2012, 2015, 2015, 2015], dtype='int64', name='date')
Run Code Online (Sandbox Code Playgroud)

有趣的是,当使用groupby方法时,您可以传递一个函数.此函数将隐式传递DataFrame的索引.因此,我们可以通过以下方式从上面得到相同的结果:

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

      sum  mean  max
2012   14     7    9
2015    6     2    3
Run Code Online (Sandbox Code Playgroud)

使用该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
Run Code Online (Sandbox Code Playgroud)

转换为pandas Period

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

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

0   2012
1   2012
2   2015
3   2015
4   2015
Name: date, dtype: object
Run Code Online (Sandbox Code Playgroud)

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

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


      sum  mean  max
2012   14     7    9
2015    6     2    3
Run Code Online (Sandbox Code Playgroud)

  • @ Shiv_90"A"是时间序列偏移别名:https://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases (2认同)

eca*_*mur 13

这应该工作:

data.groupby(lambda x: data['date'][x].year)
Run Code Online (Sandbox Code Playgroud)