使用Matplotlib绘制折线图与直方图组合图遇异常求助
解决Matplotlib双轴折线图+直方图(或柱状图)的异常问题
你的代码出现异常的核心原因是:hist()函数的作用是统计PDO数据的频数分布,它的x轴代表PDO的数值区间,而折线图的x轴是年份,两者x轴的含义完全不匹配,叠加后自然图形混乱。
根据你的需求(x轴范围一致,双轴对应不同y轴范围),分两种场景给出解决方案:
场景1:每个年份对应一个PDO数据(折线+柱状图,x轴均为年份)
这是最符合“x轴范围一致”需求的方案,把PDO用柱状图展示,和折线图的年份x轴一一对应:
import matplotlib.pyplot as plt import pandas as pd # 假设dat包含Year、frequency、PDO列,Year为年份序列 fig, ax1 = plt.subplots(figsize=(10, 6)) # 绘制frequency折线图 ax1.plot(dat['Year'], dat['frequency'], '-s', color='green', markersize=7, linewidth=5, alpha=0.7, label='frequency') ax1.set_xlabel('Year') ax1.set_ylabel('frequency') # 设置指定y轴范围 ax1.set_ylim(0, 80) # 调整y轴刻度颜色匹配折线 ax1.tick_params(axis='y', labelcolor='green') # 创建双轴,绘制PDO柱状图 ax2 = ax1.twinx() # 调整柱状宽度避免和折线标记重叠 ax2.bar(dat['Year'], dat['PDO'], color='deeppink', alpha=0.7, width=0.6, label='PDO') ax2.set_ylabel('PDO') # 设置指定y轴范围 ax2.set_ylim(-2, 1) # 调整y轴刻度颜色匹配柱状图 ax2.tick_params(axis='y', labelcolor='deeppink') # 合并双轴图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper right') plt.tight_layout() plt.show()
场景2:展示PDO的分布直方图(同时匹配折线图的年份x轴范围)
如果你确实需要展示PDO的整体分布,同时让直方图的x轴范围和折线图的年份范围对齐,可以这样调整:
import matplotlib.pyplot as plt import pandas as pd fig, ax1 = plt.subplots(figsize=(10, 6)) # 绘制frequency折线图 ax1.plot(dat['Year'], dat['frequency'], '-s', color='green', markersize=7, linewidth=5, alpha=0.7, label='frequency') ax1.set_xlabel('Year') ax1.set_ylabel('frequency') ax1.set_ylim(0, 80) ax1.tick_params(axis='y', labelcolor='green') # 获取折线图的x轴范围 x_min, x_max = ax1.get_xlim() # 双轴绘制PDO直方图(密度分布适配y轴范围) ax2 = ax1.twinx() # 绘制密度直方图,让y轴范围适配需求 n, bins, patches = ax2.hist(dat['PDO'], bins=10, color='deeppink', alpha=0.7, density=True, label='PDO Distribution') ax2.set_ylabel('PDO Density') # 根据密度值调整y轴范围(这里设置为0-1,若需要负区间可考虑镜像处理) ax2.set_ylim(0, 1) ax2.tick_params(axis='y', labelcolor='deeppink') # 强制直方图x轴范围和折线图一致 ax2.set_xlim(x_min, x_max) # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper right') plt.tight_layout() plt.show()
关键说明
- 优先选择场景1,因为它完全满足“x轴范围一致(均为年份)”的核心需求,图形逻辑更清晰。
- 若使用直方图,注意它的x轴本质是PDO的数值区间,和年份x轴仅范围一致,含义不同,需根据实际需求选择。
内容的提问来源于stack exchange,提问作者shibashiba
相关产品推荐
相关产品推荐

