咨询:如何绘制含多聚合指标的时序堆叠面积图
搞定按小时统计的堆叠面积图(x轴按天汇总)
嘿,我太懂你这种折线图画得溜,转堆叠面积图就卡壳的感觉了!其实核心就是先把数据处理成按小时聚合、按天规整的结构,不管用Pandas+Matplotlib还是你熟悉的Bokeh,都能轻松实现。下面给你两种简洁的方案:
方案一:Pandas + Matplotlib 静态图首选
1. 先把数据捋顺
首先得确保时间戳是datetime类型,然后按小时聚合你的统计值(这里用求和,你可以换成mean()之类的,看你需求):
import pandas as pd import matplotlib.pyplot as plt # 假设你的数据集叫df,列是['timestamp', 'col1', 'col2', 'col3'] df['timestamp'] = pd.to_datetime(df['timestamp']) # 按小时聚合,把每个小时的统计值合并 hourly_df = df.resample('H', on='timestamp').sum().reset_index() # 提取日期和小时,方便后续按天整理x轴 hourly_df['date'] = hourly_df['timestamp'].dt.date hourly_df['hour'] = hourly_df['timestamp'].dt.hour
2. 画堆叠面积图
如果想要x轴是连续的时间(按小时走),但刻度按天显示,直接用Pandas的plot.area()就行:
plt.figure(figsize=(12, 6)) # 直接调用堆叠面积图 hourly_df.set_index('timestamp')[['col1', 'col2', 'col3']].plot.area(stacked=True, alpha=0.7) # 让x轴刻度自动适配日期,避免挤在一起 plt.gcf().autofmt_xdate() plt.xlabel('日期') plt.ylabel('统计值') plt.title('一周内按小时统计的堆叠面积图') plt.legend(title='统计列') plt.tight_layout() plt.show()
要是你想把每天的24小时单独对比,x轴只显示0-23点,不同日期作为不同的堆叠组,可以这么搞:
plt.figure(figsize=(12, 6)) # 遍历每一天,画当天的堆叠面积 for date in hourly_df['date'].unique(): day_data = hourly_df[hourly_df['date'] == date].set_index('hour')[['col1', 'col2', 'col3']] day_data.plot.area(stacked=True, alpha=0.5, label=str(date), ax=plt.gca()) plt.xlabel('小时') plt.ylabel('统计值') plt.title('每天按小时统计的堆叠面积对比') plt.legend(title='日期') plt.tight_layout() plt.show()
方案二:Bokeh 交互式图首选
既然你之前用过Bokeh,那直接用它的varea_stack函数就能搞定,还能做交互式的:
from bokeh.plotting import figure, show from bokeh.models import DatetimeTickFormatter # 预处理数据和方案一的hourly_df一致 hourly_df['timestamp'] = pd.to_datetime(hourly_df['timestamp']) # 创建绘图对象 p = figure(x_axis_type='datetime', width=800, height=400, title='一周按小时统计的堆叠面积图') # 定义要堆叠的列 stack_cols = ['col1', 'col2', 'col3'] # 绘制堆叠面积,指定颜色区分 p.varea_stack(stack_cols, x='timestamp', color=['#007bff', '#28a745', '#dc3545'], source=hourly_df) # 配置x轴按天显示,旋转标签避免重叠 p.xaxis.formatter = DatetimeTickFormatter(days=['%Y-%m-%d']) p.xaxis.major_label_orientation = 3.14/4 # 调整图例顺序(Bokeh默认堆叠顺序和图例反过来) p.legend.items = [p.legend.items[i] for i in reversed(range(len(stack_cols)))] p.legend.title = '统计列' show(p)
小提醒
- 必须先按小时聚合数据!不然原始时间戳太密集,堆叠面积会糊成一片;
- 聚合方式选对:计数类用
sum(),均值类用mean(); - 喜欢静态图选Matplotlib,要交互(缩放、hover看数据)选Bokeh。
内容的提问来源于stack exchange,提问作者mikernova
相关产品推荐
相关产品推荐

