如何用Matplotlib绘制分组柱状图叠加折线图并解决显示问题
问题解决:用Matplotlib复现Excel组合图表
目标图表
需要复现的是包含分组柱状图(展示两类占比分布)和双折线图(展示两类事件率)的双Y轴组合图表。
表格数据
| Category | %_total_dist_1 | event_rate_%_1 | %_total_dist_2 | event_rate_%_2 |
|---|---|---|---|---|
| 00 (-inf, 0.25) | 5.7 | 36.5 | 5.8 | 10 |
| 01 [0.25, 4.75) | 7 | 11.2 | 7 | 11 |
| 02 [4.75, 6.75) | 10.5 | 5 | 10.5 | 4.8 |
| 03 [6.75, 8.25) | 13.8 | 3.9 | 13.7 | 4 |
| 04 [8.25, 9.25) | 9.1 | 3.4 | 9.2 | 3.1 |
| 05 [9.25, 10.75) | 14.1 | 2.5 | 14.2 | 2.4 |
| 06 [10.75, 11.75) | 13.7 | 1.6 | 13.7 | 1.8 |
| 07 [11.75, 13.75) | 16.8 | 1.3 | 16.7 | 1.3 |
| 08 [13.75, inf) | 9.4 | 1 | 9.1 | 1.3 |
遇到的问题
- 柱状图出现重叠
- X轴标签未旋转,导致文字重叠
- 需要为折线图添加标记点
原代码
import pandas as pd import matplotlib.pyplot as plt # Create a Pandas DataFrame with your data data = { "Category": ["00 (-inf, 0.25)", "01 [0.25, 4.75)", "02 [4.75, 6.75)", "03 [6.75, 8.25)", "04 [8.25, 9.25)", "05 [9.25, 10.75)", "06 [10.75, 11.75)", "07 [11.75, 13.75)", "08 [13.75, inf)"], "%_total_dist_1": [5.7, 7, 10.5, 13.8, 9.1, 14.1, 13.7, 16.8, 9.4], "event_rate_%_1": [36.5, 11.2, 5, 3.9, 3.4, 2.5, 1.6, 1.3, 1], "%_total_dist_2": [5.8, 7, 10.5, 13.7, 9.2, 14.2, 13.7, 16.7, 9.1], "event_rate_%_2": [10, 11, 4.8, 4, 3.1, 2.4, 1.8, 1.3, 1.3] } df = pd.DataFrame(data) # Create a figure and primary y-axis fig, ax1 = plt.subplots(figsize=(10, 6)) # Plot percentage distribution on the primary y-axis ax1.bar(df['Category'], df['%_total_dist_1'], alpha=0.7, label="%_total_dist_1", color='b') ax1.bar(df['Category'], df['%_total_dist_2'], alpha=0.7, label="%_total_dist_2", color='g') ax1.set_ylabel('% Distribution', color='b') ax1.tick_params(axis='y', labelcolor='b') # Create a secondary y-axis ax2 = ax1.twinx() # Plot event rate on the secondary y-axis ax2.plot(df['Category'], df['event_rate_%_1'], marker='o', label='event_rate_%_1', color='r') ax2.plot(df['Category'], df['event_rate_%_2'], marker='o', label='event_rate_%_2', color='orange') ax2.set_ylabel('Event Rate (%)', color='r') ax2.tick_params(axis='y', labelcolor='r') # Adding legend fig.tight_layout() plt.title('Percentage Distribution and Event Rate') fig.legend(loc="upper left", bbox_to_anchor=(0.15, 0.85)) # Rotate x-axis labels for better readability plt.xticks(rotation=45, ha="right") # Show the plot plt.show()
修正后的代码
import pandas as pd import matplotlib.pyplot as plt import numpy as np # 构建数据 data = { "Category": ["00 (-inf, 0.25)", "01 [0.25, 4.75)", "02 [4.75, 6.75)", "03 [6.75, 8.25)", "04 [8.25, 9.25)", "05 [9.25, 10.75)", "06 [10.75, 11.75)", "07 [11.75, 13.75)", "08 [13.75, inf)"], "%_total_dist_1": [5.7, 7, 10.5, 13.8, 9.1, 14.1, 13.7, 16.8, 9.4], "event_rate_%_1": [36.5, 11.2, 5, 3.9, 3.4, 2.5, 1.6, 1.3, 1], "%_total_dist_2": [5.8, 7, 10.5, 13.7, 9.2, 14.2, 13.7, 16.7, 9.1], "event_rate_%_2": [10, 11, 4.8, 4, 3.1, 2.4, 1.8, 1.3, 1.3] } df = pd.DataFrame(data) # 创建画布和主Y轴 fig, ax1 = plt.subplots(figsize=(12, 6)) # 设置X轴索引和柱子宽度 x = np.arange(len(df['Category'])) width = 0.35 # 绘制分组柱状图,避免重叠 bar1 = ax1.bar(x - width/2, df['%_total_dist_1'], width, alpha=0.7, label="%_total_dist_1", color='blue') bar2 = ax1.bar(x + width/2, df['%_total_dist_2'], width, alpha=0.7, label="%_total_dist_2", color='green') # 主Y轴设置 ax1.set_ylabel('占比分布 (%)', color='blue') ax1.tick_params(axis='y', labelcolor='blue') # 设置X轴标签并旋转45度,右对齐 ax1.set_xticks(x) ax1.set_xticklabels(df['Category'], rotation=45, ha='right') # 创建副Y轴 ax2 = ax1.twinx() # 绘制带标记点的折线图 line1, = ax2.plot(x, df['event_rate_%_1'], marker='o', markersize=6, label='event_rate_%_1', color='red') line2, = ax2.plot(x, df['event_rate_%_2'], marker='s', markersize=6, label='event_rate_%_2', color='orange') # 副Y轴设置 ax2.set_ylabel('事件率 (%)', color='red') ax2.tick_params(axis='y', labelcolor='red') # 合并图例 ax1.legend(handles=[bar1, bar2, line1, line2], loc="upper left") # 调整布局,防止标签被截断 plt.title('占比分布与事件率') fig.tight_layout() plt.show()
关键修正说明
- 解决柱状图重叠:用
np.arange生成X轴数值索引,给两组柱子分别设置x - width/2和x + width/2的位置,实现分组排列。 - X轴标签旋转:直接在主轴
ax1上设置xticklabels时添加rotation=45和ha='right',确保标签旋转后对齐整齐,避免重叠。 - 折线标记点:保留
marker参数,通过markersize调整标记大小,用不同形状(圆形、方形)区分两组数据,提升辨识度。
内容的提问来源于stack exchange,提问作者bunti papu
相关产品推荐
相关产品推荐

