如何按非唯一列中的日期对 Pandas DataFrame 条目进行分组
- 2025-04-16 08:57:00
- admin 原创
- 14
问题描述:
PandasDataFrame
包含一个"date"
包含非唯一datetime
值的列。我可以使用以下方法对这个框架中的行进行分组:
data.groupby(data['date'])
但是,这会按值拆分数据datetime
。我想按“日期”列中存储的年份对这些数据进行分组。此页面展示了如何在使用时间戳作为索引的情况下按年份分组,而我的情况并非如此。
我如何实现这种分组?
解决方案 1:
我正在使用 Pandas 0.16.2。它在我的大型数据集上表现更好:
data.groupby(data.date.dt.year)
使用该dt
选项并进行操作weekofyear
等dayofweek
变得更加容易。
解决方案 2:
ecatmur 的解决方案会很好用。不过,在大型数据集上,它的性能会更好:
data.groupby(data['date'].map(lambda x: x.year))
解决方案 3:
使用样本数据集可能更容易解释这一点。
创建示例数据
假设我们有一列时间戳,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
参数指定该列。您还需要将偏移量别名指定为字符串。
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 对象。我们必须将偏移量别名作为字符串传入,以确定 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
解决方案 4:
这应该可行:
data.groupby(lambda x: data['date'][x].year)
解决方案 5:
这也行得通
data.groupby(data['date'].dt.year)
解决方案 6:
使用:
data.groupby(['col1', data.date.dt.year]).agg({'col2': 'agg_func'}).reset_index()
如果您想按日期时间列中的年份分组,也可以按另一个不同类型的列(col1)分组
解决方案 7:
Boris Gorelik给DACW 的 回复打了“最佳答案”的标签,这似乎表明他很乐意将数据框“分组”成 内的小数据框DataFrameGroupBy object
。其他贡献者的回复也秉持着同样的理念。
处理包含大量事件记录的数据集,每个用户有多个事件,如果想要按年份创建唯一用户计数的数据集(用于绘制图表或快速汇总统计),Ted Petrou的回应更为贴切,因为它包含聚合。
因此,采用df
包含日期列'Enrollment Begin'
和名为的数据列的数据框'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 值的模式,因此您可以看到它们在哪里上升和下降。
通过回顾每种方法我学到了很多东西,非常感谢所有的贡献者。
扫码咨询,免费领取项目管理大礼包!