如何在Matplotlib中绘制含Datetime轴的柱状图与折线图组合图
解决方案:DatetimeIndex下混合柱状图与折线图+动态日期刻度
我来帮你搞定这个需求!其实不用纠结DateFormatter,pandas结合matplotlib就能完美解决动态日期刻度的问题,而且代码还很简洁。先把你未完成的代码补全,再给出完整的实现方案:
首先补全测试用的DataFrame生成代码:
import matplotlib.pyplot as plt import pandas as pd import datetime as dt import numpy as np startDate = dt.datetime(2018,1,1,0,0) nrHours = 144 # 生成每小时间隔的DatetimeIndex datetimeIndex = pd.date_range(start=startDate, periods=nrHours, freq='H') # 生成两列随机整数测试数据 df = pd.DataFrame({ 'Col1': np.random.randint(10, 50, size=nrHours), 'Col2': np.random.randint(50, 100, size=nrHours) }, index=datetimeIndex)
接下来是核心绘图部分,关键是利用pandas对DatetimeIndex的原生支持,它会自动处理x轴的动态刻度适配——缩放图表时,标签会智能切换时间粒度(比如缩小显示日期,放大显示小时),完全不用手动配置格式化器:
# 创建画布和主轴对象 fig, ax1 = plt.subplots(figsize=(12,6)) # 绘制Col1的柱状图 ax1.bar(df.index, df['Col1'], width=0.04, label='Col1', color='tab:blue') ax1.set_xlabel('日期时间') ax1.set_ylabel('Col1 数值', color='tab:blue') ax1.tick_params(axis='y', labelcolor='tab:blue') # 创建副轴用于绘制Col2的折线图(如果两列数值范围接近,可跳过这步直接用主轴) ax2 = ax1.twinx() ax2.plot(df.index, df['Col2'], color='tab:orange', linewidth=2, label='Col2') ax2.set_ylabel('Col2 数值', color='tab:orange') ax2.tick_params(axis='y', labelcolor='tab:orange') # 合并两个轴的图例,方便查看 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left') # 旋转x轴标签避免重叠,提升可读性 plt.xticks(rotation=45, ha='right') # 自动调整布局,防止标签被截断 plt.tight_layout() plt.show()
为什么这个方案能满足你的需求?
- 动态日期刻度:pandas与matplotlib的组合会自动识别DatetimeIndex的时间粒度,缩放图表时x轴标签会智能切换——比如缩小到天级时显示
2018-01-01,放大到小时级时显示2018-01-01 08:00,完全不需要手动设置DateFormatter。 - 混合图表兼容:通过双轴(或单轴)实现柱状图与折线图的同图展示,同时保证两个数据系列的数值都能清晰呈现。
- 可读性优化:通过旋转标签和自动布局,避免了日期标签重叠的问题。
如果Col1和Col2的数值范围接近,也可以简化为单轴绘制,代码更简洁:
fig, ax = plt.subplots(figsize=(12,6)) df['Col1'].plot(kind='bar', ax=ax, width=0.04, label='Col1') df['Col2'].plot(kind='line', ax=ax, color='tab:orange', linewidth=2, label='Col2') ax.set_xlabel('日期时间') ax.set_ylabel('数值') ax.legend() plt.xticks(rotation=45, ha='right') plt.tight_layout() plt.show()
内容的提问来源于stack exchange,提问作者Christopher H
相关产品推荐
相关产品推荐

