按网站与4小时时间间隔分组的响应时间柱状图优化问题
问题描述
我有一个存储请求响应时间的pandas DataFrame,数据如下:
execution_time request_type response_time_ms URL Error 2 2023-10-12 08:52:16 Google 91.0 https://www.google.com NaN 3 2023-10-12 08:52:16 CNN 115.0 https://edition.cnn.com NaN 6 2023-10-12 08:52:27 Google 90.0 https://www.google.com NaN 7 2023-10-12 08:52:27 CNN 105.0 https://edition.cnn.com NaN 10 2023-10-12 08:52:37 Google 5111.0 https://www.google.com NaN
数据包含请求时间、作为网站名称的request_type以及响应时间。我希望生成按网站(request_type)和4小时时间间隔分组的中位数响应时间柱状图,以展示响应时间随时段的变化。目前已实现绘图,但存在以下问题:
- 不同网站无法用不同颜色区分
- 希望将同一时段的网站响应时间堆叠显示(或至少实现颜色区分)
- 图例中出现“none, none”的无效内容
现有代码:
df_by_time = df.groupby(["request_type", pd.Grouper(key="execution_time", freq="4h")]).agg({"response_time_ms": ["median"]}) df_by_time.plot(kind='bar', figsize=(8, 6), title='Response Times', xlabel='Type', ylabel='Response time [ms]', rot=90)
解决方案
1. 修复分组后的列结构,解决图例异常
分组后生成的多层列索引(response_time_ms + median)是图例显示“none, none”的根源。可以简化分组逻辑,直接提取中位数并重置索引:
# 分组计算中位数,同时避免多层列索引 df_by_time = df.groupby(["request_type", pd.Grouper(key="execution_time", freq="4h")])["response_time_ms"].median().reset_index() # 可选:将时间格式转为易读字符串,优化x轴显示 df_by_time['execution_time'] = df_by_time['execution_time'].dt.strftime('%Y-%m-%d %H:%M')
2. 重塑数据结构,支持颜色区分与堆叠
使用pivot将数据转为时段为行、网站为列的宽表格式,这样绘图时会自动为不同网站分配独立颜色,且支持堆叠:
# 重塑数据,缺失值填充为0(避免无数据的网站不显示) df_pivot = df_by_time.pivot(index='execution_time', columns='request_type', values='response_time_ms').fillna(0)
3. 绘制目标柱状图
现在可以直接绘制堆叠柱状图(或普通分组柱状图),图例将正确显示网站名称,颜色自动区分:
# 绘制堆叠柱状图 ax = df_pivot.plot(kind='bar', stacked=True, figsize=(8, 6), title='Median Response Times by 4-hour Interval', xlabel='4-hour Interval', ylabel='Response Time [ms]', rot=90) # 若不需要堆叠,去掉stacked=True即可得到分组柱状图 # ax = df_pivot.plot(kind='bar', figsize=(8, 6), ...) # 可选:调整图例位置,避免遮挡图表 ax.legend(title='Website', bbox_to_anchor=(1.05, 1), loc='upper left')
完整可运行代码
import pandas as pd # 构建示例数据 data = { 'execution_time': ['2023-10-12 08:52:16', '2023-10-12 08:52:16', '2023-10-12 08:52:27', '2023-10-12 08:52:27', '2023-10-12 08:52:37'], 'request_type': ['Google', 'CNN', 'Google', 'CNN', 'Google'], 'response_time_ms': [91.0, 115.0, 90.0, 105.0, 5111.0], 'URL': ['https://www.google.com', 'https://edition.cnn.com', 'https://www.google.com', 'https://edition.cnn.com', 'https://www.google.com'], 'Error': [None, None, None, None, None] } df = pd.DataFrame(data) df['execution_time'] = pd.to_datetime(df['execution_time']) # 分组计算中位数 df_by_time = df.groupby(["request_type", pd.Grouper(key="execution_time", freq="4h")])["response_time_ms"].median().reset_index() df_by_time['execution_time'] = df_by_time['execution_time'].dt.strftime('%Y-%m-%d %H:%M') # 重塑数据结构 df_pivot = df_by_time.pivot(index='execution_time', columns='request_type', values='response_time_ms').fillna(0) # 绘图 ax = df_pivot.plot(kind='bar', stacked=True, figsize=(8, 6), title='Median Response Times by 4-hour Interval', xlabel='4-hour Interval', ylabel='Response Time [ms]', rot=90) ax.legend(title='Website', bbox_to_anchor=(1.05, 1), loc='upper left')
内容的提问来源于stack exchange,提问作者beginner_
相关产品推荐
相关产品推荐

