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

问题描述 投票:0回答:7

Pandas

DataFrame
包含名为
"date"
的列,其中包含非唯一的
datetime
值。 我可以使用以下方法对这个框架中的线条进行分组:

data.groupby(data['date'])

但是,这会按

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

如何实现这种分组?

python pandas
7个回答
138
投票

我使用的是pandas 0.16.2。这在我的大型数据集上有更好的性能:

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

使用

dt
选项并使用
weekofyear
dayofweek
等变得更加容易。


81
投票

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

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

46
投票

使用示例数据集可能更容易解释。

创建示例数据

假设我们有一个时间戳列,

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

按年份分组有多种方法

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

.dt
具有
year
属性

的访问器

当您有一列(而不是索引)pandas 时间戳时,您可以使用

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
参数指定该列。您还需要将 offsetalias 指定为字符串。

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

转换为pandas时期

您还可以将日期列转换为 pandas 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

16
投票

这应该有效:

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

1
投票

这也可以工作

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


1
投票

用途:

data.groupby(['col1', data.date.dt.year]).agg({'col2': 'agg_func'}).reset_index()

如果您想按日期时间列中的年份以及另一个不同类型的列(col1)进行分组


0
投票

Boris GorelikDACW response 给出了最佳答案,这似乎表明他很高兴将数据帧“分组”为

DataFrameGroupBy object
内的小数据帧。其他贡献者也有类似的反应。

使用事件记录的大型数据集,每个用户有多个事件,如果想要按年份创建唯一用户计数的数据集(用于图表或快速汇总统计),Ted Petrouresponse 是更相关,因为它包括聚合。

因此,采用包含日期列

df
和名为
'Enrollment Begin'
的 ID 值列的数据框
'Requester Return Field'
,要获取按年份列出的唯一 ID 值计数,可以使用:

gby = (df.groupby(df['Enrollment Begin'].dt.year)['Requester Return Field'].agg(['nunique']))

输出如下:

                  nunique
Enrollment Begin         
1995.0                  1
...
2022.0               6725
2023.0               3730
2024.0               1802

返回的数据快速视图按年份显示唯一 ID 值的模式,以便您可以看到它们的上升和下降位置。

通过回顾每种方法,我学到了很多东西,非常感谢所有贡献者。

© www.soinside.com 2019 - 2024. All rights reserved.