You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

时序数据同画布绘双柱状图与折线图:折线不显示问题排查

问题分析与修复方案

核心问题及修复点

  • 双轴重叠遮挡折线:连续两次调用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()

关键修复说明

  1. 轴位置调整:通过ax3.spines['right'].set_position(('axes', 1.15))将第三个轴移至更右侧,避免与第二个轴重叠。
  2. 折线图增强:添加marker='o'和linewidth=2让折线更醒目,同时明确标注y轴单位。
  3. 标签写法修正:将赋值式的ax1.set_ylabel = ('...')改为函数调用ax1.set_ylabel('...'),确保轴标签正常显示。
  4. 标注偏移优化:调整xytext参数,避免数值标签被画布底部截断。
  5. 刻度简化:直接使用分组后的年份索引作为x轴刻度,无需多余的日期转换操作。

内容的提问来源于stack exchange,提问作者Rozita Ghasemi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 23:57:24