时序数据同画布绘双柱状图与折线图:折线不显示问题排查
问题分析与修复方案
核心问题及修复点
- 双轴重叠遮挡折线:连续两次调用
twinx()会让ax2和ax3的右侧轴完全重叠,折线图被覆盖无法显示,需手动调整ax3的位置。 - 数据量级差异导致折线不可见:失业率是百分比(数值通常为个位数),而许可价值是大额数值,ax3的y轴范围被柱状图数据压缩到几乎不可见,需单独设置轴范围或确保轴独立。
- 轴标签赋值错误:
set_ylabel是方法而非属性,不能直接赋值,必须用函数调用形式设置标签。 - 错误调用标注函数:
add_labels是处理柱状图矩形元素的,折线图没有patches属性,调用ax3会引发报错,仅需对ax1和ax2调用该函数。 - 索引与刻度处理冗余:分组后的Date列已是年份整数,无需转datetime再格式化,直接用索引值作为刻度即可。
- 变量未定义:代码中
re_df未定义,需补充re_df = df完成赋值。
修正后的完整代码
import pandas as pd import matplotlib.pyplot as plt import datetime pd.set_option('display.max_colwidth', 100) df = pd.read_csv('Monthly_Economic_Indicators.csv') # 日期格式转换函数 def dateobject(date): dateobject = datetime.datetime.strptime(str(date), "%Y-%m-%d") dateobject = dateobject.isoformat() return dateobject df['Date'] = df['Date'].map(dateobject) re_df = df # 补充缺失的变量定义 re_df['Date'] = pd.to_datetime(re_df['Date']) # 按年份分组聚合数据 result = re_df.groupby(re_df['Date'].dt.year).agg({ 'Residential_Permit_Value': 'sum', 'NonResidential_Permit_Value':'sum', 'Unemployment_Rate': 'mean' }).reset_index() result = result.set_index(['Date']) # 创建画布与坐标轴 fig = plt.figure(figsize=(12, 8)) # 调整为更合理的尺寸 ax1 = fig.add_subplot(111) ax2 = ax1.twinx() ax3 = ax1.twinx() # 调整第三个轴的位置,避免与第二个轴重叠 ax3.spines['right'].set_position(('axes', 1.15)) # 绘制并列柱状图 result['Residential_Permit_Value'].plot( kind='bar', color='pink', ax=ax1, position=0, width=0.25, label="Residential Permit Value" ) result['NonResidential_Permit_Value'].plot( kind='bar', color='yellow', ax=ax2, position=1, width=0.25, label="Non-Residential Permit Value" ) # 绘制折线图,添加标记点增强可视性 result['Unemployment_Rate'].plot( kind='line', color='red', ax=ax3, marker='o', linewidth=2, label='Unemployment Rate' ) # 设置坐标轴标签(修正方法调用方式) ax1.set_ylabel('Residential Permit Value') ax2.set_ylabel('Non-Residential Permit Value') ax3.set_ylabel('Unemployment Rate (%)') # 设置图例位置 ax1.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc='lower left') ax2.legend(bbox_to_anchor=(0., 1.08, 1., .102), loc='lower left') ax3.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc='lower right') # 柱状图数值标注函数 def add_labels(ax): for rect in ax.patches: y_value = rect.get_height() x_value = rect.get_x() + rect.get_width() / 2. label = '${:,.2f}'.format(y_value) ax.annotate( label, (x_value, y_value), xytext=(0, 5), # 调整偏移量,避免标签被截断 textcoords="offset points", ha='center', va='bottom', rotation='vertical', weight='bold' ) # 仅对柱状图坐标轴调用标注函数 add_labels(ax1) add_labels(ax2) # 设置x轴刻度为年份(简化处理) ax1.set_xticklabels(result.index, rotation=0) plt.tight_layout() plt.show()
关键修复说明
- 轴位置调整:通过
ax3.spines['right'].set_position(('axes', 1.15))将第三个轴移至更右侧,避免与第二个轴重叠。 - 折线图增强:添加
marker='o'和linewidth=2让折线更醒目,同时明确标注y轴单位。 - 标签写法修正:将赋值式的
ax1.set_ylabel = ('...')改为函数调用ax1.set_ylabel('...'),确保轴标签正常显示。 - 标注偏移优化:调整
xytext参数,避免数值标签被画布底部截断。 - 刻度简化:直接使用分组后的年份索引作为x轴刻度,无需多余的日期转换操作。
内容的提问来源于stack exchange,提问作者Rozita Ghasemi
相关产品推荐
相关产品推荐

