按日期与小时分组统计记录数并可视化的技术需求
解决按日期+小时分组统计并绘图的问题
我明白你的问题啦——之前的代码把不同日期的同一小时数据合并了,没法区分是5月31日17点还是6月1日17点的记录。下面给你一步步解决:
第一步:正确按日期+小时分组统计记录数
你需要把时间戳聚合到「日期-小时」的粒度,而不是只提取小时数。这里有两种简洁的方法:
方法1:用dt.floor('H')分组
先确保你的DataFrame索引是datetime类型(如果还不是的话先转换),然后把每个时间戳向下取整到当前小时,再分组计数:
import pandas as pd # 先把原始数据的时间列设为索引并转换为datetime类型 df = df.set_index('Unnamed: 0') df.index = pd.to_datetime(df.index) # 按日期+小时分组,统计总记录数 hourly_counts = df.groupby(df.index.floor('H')).size().reset_index(name='Amount') # 可选:把日期格式改成你想要的「YYYY-MM-DD HH」样式 hourly_counts['Date'] = hourly_counts['Unnamed: 0'].dt.strftime('%Y-%m-%d %H') # 重命名列名更直观 hourly_counts.rename(columns={'Unnamed: 0': 'Date'}, inplace=True)
方法2:用resample(更简洁)
pandas的resample专门用于时间序列的重采样,按小时聚合非常方便:
# 同样先确保索引是datetime类型 df.index = pd.to_datetime(df.index) # 按小时重采样,统计每个时段的记录数 hourly_counts = df.resample('H').size().reset_index(name='Amount') # 可选:格式化日期显示 hourly_counts['Date'] = hourly_counts['index'].dt.strftime('%Y-%m-%d %H') hourly_counts.drop(columns='index', inplace=True)
两种方法最终都会得到你想要的格式:
| Date | Amount |
|---|---|
| 2020-05-31 17 | 60 |
| 2020-05-31 18 | 58 |
| ... | ... |
| 2020-06-01 11 | 42 |
第二步:基于分组数据绘图
现在有了正确的分组数据,直接绘制柱状图即可,注意旋转x轴标签避免重叠:
import matplotlib.pyplot as plt # 用matplotlib原生绘图 plt.figure(figsize=(12, 6)) plt.bar(hourly_counts['Date'], hourly_counts['Amount'], color='#1f77b4') plt.xticks(rotation=45, ha='right') # 旋转标签,让文字更易读 plt.xlabel('Date & Hour') plt.ylabel('Total Records') plt.title('Hourly Record Counts by Date') plt.tight_layout() # 自动调整布局,防止标签被截断 plt.show() # 或者用pandas的plot方法更快捷 hourly_counts.set_index('Date')['Amount'].plot(kind='bar', figsize=(12, 6), rot=45) plt.xlabel('Date & Hour') plt.ylabel('Total Records') plt.title('Hourly Record Counts by Date') plt.tight_layout() plt.show()
为什么之前的代码有问题?
你之前的代码df.groupby([df.index.hour, 'PanelistID'])['PanelistID'].count()做了两件不符合需求的事:
- 只按小时数(不管日期)分组,导致5月31日17点和6月1日17点的数据被合并;
- 还按
PanelistID拆分了统计,得到的是每个用户在对应小时的记录数,而不是该时段的总记录数。
去掉PanelistID的分组,换成按「日期+小时」的时间维度,就解决问题啦~
内容的提问来源于stack exchange,提问作者B.W.
相关产品推荐
相关产品推荐

