求助:如何用Matplotlib绘制共享X轴的多分组数据图表?
调整Matplotlib代码以生成按API分组的预期多子图时间序列图表
我想要绘制类似示例图的多子图时间序列图表,目前编写了代码但没得到预期效果,当前生成的图表和按Server分组的图表也不符合需求,希望得到指导。
我当前的代码:
import matplotlib.pyplot as plt import pandas as pd data_set= [ {'date':'2018-05-20','server':'server1','api':'api1','count':4}, {'date':'2018-05-21','server':'server1','api':'api1','count':6}, {'date':'2018-05-22','server':'server1','api':'api1','count':10}, {'date':'2018-05-23','server':'server1','api':'api1','count':10}, {'date':'2018-05-24','server':'server1','api':'api1','count':14}, {'date':'2018-05-20','server':'server1','api':'api2','count':20}, {'date':'2018-05-21','server':'server1','api':'api2','count':22}, {'date':'2018-05-22','server':'server1','api':'api2','count':20}, {'date':'2018-05-23','server':'server1','api':'api2','count':23}, {'date':'2018-05-24','server':'server1','api':'api2','count':20}, {'date':'2018-05-24','server':'server2','api':'api1','count':30}, {'date':'2018-05-21','server':'server2','api':'api2','count':20} ] f, (axs) = plt.subplots(3, sharex=True, sharey=True) df = pd.DataFrame(data_set) df['date'] = pd.to_datetime(df['date'],format='%Y/%m/%d %H:%M:%S') df = df.set_index('date') grouped = df.groupby(['api']) for (name, df1), ax in zip(grouped, axs.flat): df1.plot(y='count', ax=ax) plt.legend(bbox_to_anchor=(1, 1, 0.25, -0.2), bbox_transform=plt.gcf().transFigure) f.subplots_adjust(hspace=0) plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
问题分析:
- 日期解析格式错误:原数据的
date是YYYY-MM-DD格式,但代码里用了%Y/%m/%d %H:%M:%S,虽然后续Pandas可能自动兼容,但规范匹配格式能避免潜在问题 - 子图数量不匹配:API只有
api1和api2两个分组,但创建了3个子图,会多出一个空图 - 未按Server区分线条:每个API子图里没有拆分不同Server的数据,导致所有数据画成一条线,无法区分不同服务器的表现
- 图例设置不合理:全局图例没有对应到正确的Server标识,显示混乱
修正后的代码:
import matplotlib.pyplot as plt import pandas as pd data_set= [ {'date':'2018-05-20','server':'server1','api':'api1','count':4}, {'date':'2018-05-21','server':'server1','api':'api1','count':6}, {'date':'2018-05-22','server':'server1','api':'api1','count':10}, {'date':'2018-05-23','server':'server1','api':'api1','count':10}, {'date':'2018-05-24','server':'server1','api':'api1','count':14}, {'date':'2018-05-20','server':'server1','api':'api2','count':20}, {'date':'2018-05-21','server':'server1','api':'api2','count':22}, {'date':'2018-05-22','server':'server1','api':'api2','count':20}, {'date':'2018-05-23','server':'server1','api':'api2','count':23}, {'date':'2018-05-24','server':'server1','api':'api2','count':20}, {'date':'2018-05-24','server':'server2','api':'api1','count':30}, {'date':'2018-05-21','server':'server2','api':'api2','count':20} ] # 1. 正确解析日期格式 df = pd.DataFrame(data_set) df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d') df = df.set_index('date') # 2. 按API分组,获取实际分组数量 api_groups = df.groupby(['api']) num_groups = len(api_groups) # 3. 根据分组数量动态创建子图,避免空图 fig, axs = plt.subplots(num_groups, sharex=True, sharey=True, figsize=(10, 6)) fig.suptitle('API Request Count by Server Over Time', y=1.02) # 4. 遍历每个API分组,在对应子图内按Server绘制不同线条 for (api_name, api_df), ax in zip(api_groups, axs.flat): server_groups = api_df.groupby('server') for server_name, server_df in server_groups: server_df['count'].plot(ax=ax, label=server_name) ax.set_title(f'API: {api_name}') ax.legend(title='Server') ax.set_ylabel('Request Count') # 5. 调整布局与x轴显示 fig.subplots_adjust(hspace=0.3) plt.setp([a.get_xticklabels() for a in fig.axes[:-1]], visible=False) plt.xlabel('Date') plt.tight_layout() plt.show()
修正说明:
- 匹配了日期解析格式,确保数据处理准确
- 动态生成子图数量,避免多余空图
- 在每个API子图内按Server拆分数据绘制,清晰区分不同服务器的请求计数变化
- 为每个子图添加标题和图例,提升图表可读性
- 优化了整体布局和标签显示,让图表更美观专业
内容的提问来源于stack exchange,提问作者vas
相关产品推荐
相关产品推荐

