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

如何在Plotly子图中添加堆叠柱状图及双Y轴折线图?

Plotly 实现2行1列共享X轴子图(堆叠柱状+双Y轴折线)

先看简化版示例DataFrame(实际包含100+列品类数据):

import pandas as pd
import plotly.subplots as sp
import plotly.graph_objects as go

# 构造示例数据
dates = pd.date_range(start='2023-01-01', periods=6, freq='M')
df = pd.DataFrame({
    'date': dates,
    'category_1': [100, 120, 150, 180, 200, 220],
    'category_2': [80, 90, 100, 110, 130, 140],
    # ... 省略98+个类似category列
    'cost': [500, 550, 600, 680, 720, 780],
    'numSales': [20, 25, 30, 35, 40, 45]
})

实现步骤

  1. 初始化共享X轴的子图布局
    用make_subplots创建2行1列的子图,指定第一行启用双Y轴,同时开启X轴共享:

    fig = sp.make_subplots(
        rows=2, cols=1,
        specs=[[{"secondary_y": True}], [{}]],
        shared_xaxes=True,
        vertical_spacing=0.1  # 调整子图间距
    )
    
  2. 第一行添加100+列的堆叠柱状图
    遍历所有品类列(排除date、cost、numSales),逐个添加柱状图trace,Plotly会自动处理堆叠逻辑:

    # 筛选出所有品类列
    category_cols = [col for col in df.columns if col not in ['date', 'cost', 'numSales']]
    
    for col in category_cols:
        fig.add_trace(
            go.Bar(x=df['date'], y=df[col], name=col),
            row=1, col=1, secondary_y=False  # 绑定左侧Y轴
        )
    
  3. 第一行添加右侧Y轴的cost折线图
    通过secondary_y=True绑定右侧Y轴,实现类似matplotlibtwinx的效果:

    fig.add_trace(
        go.Scatter(x=df['date'], y=df['cost'], name='成本', line=dict(color='red')),
        row=1, col=1, secondary_y=True
    )
    
  4. 第二行添加numSales折线图
    直接在第二行子图添加折线,因为已开启shared_xaxes=True,会自动共享X轴:

    fig.add_trace(
        go.Scatter(x=df['date'], y=df['numSales'], name='销量'),
        row=2, col=1
    )
    
  5. 布局优化
    调整Y轴标题、图例位置等,提升可读性:

    # 设置左侧Y轴标题(品类数值)
    fig.update_yaxes(title_text="品类数值", row=1, col=1, secondary_y=False)
    # 设置右侧Y轴标题(成本)
    fig.update_yaxes(title_text="成本", row=1, col=1, secondary_y=True)
    # 设置第二行Y轴标题(销量)
    fig.update_yaxes(title_text="销量", row=2, col=1)
    # 设置X轴标题
    fig.update_xaxes(title_text="日期", row=2, col=1)
    
    # 调整图例位置,避免遮挡图表
    fig.update_layout(
        legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
        title_text="品类堆叠柱状+成本&销量趋势"
    )
    

完整运行代码

整合上述片段,直接运行即可得到目标图表:

import pandas as pd
import plotly.subplots as sp
import plotly.graph_objects as go

# 构造示例数据
dates = pd.date_range(start='2023-01-01', periods=6, freq='M')
df = pd.DataFrame({
    'date': dates,
    'category_1': [100, 120, 150, 180, 200, 220],
    'category_2': [80, 90, 100, 110, 130, 140],
    # 可自行添加更多category列测试
    'cost': [500, 550, 600, 680, 720, 780],
    'numSales': [20, 25, 30, 35, 40, 45]
})

# 创建子图
fig = sp.make_subplots(
    rows=2, cols=1,
    specs=[[{"secondary_y": True}], [{}]],
    shared_xaxes=True,
    vertical_spacing=0.1
)

# 添加堆叠柱状图
category_cols = [col for col in df.columns if col not in ['date', 'cost', 'numSales']]
for col in category_cols:
    fig.add_trace(
        go.Bar(x=df['date'], y=df[col], name=col),
        row=1, col=1, secondary_y=False
    )

# 添加成本折线图(右侧Y轴)
fig.add_trace(
    go.Scatter(x=df['date'], y=df['cost'], name='成本', line=dict(color='red')),
    row=1, col=1, secondary_y=True
)

# 添加销量折线图
fig.add_trace(
    go.Scatter(x=df['date'], y=df['numSales'], name='销量'),
    row=2, col=1
)

# 布局调整
fig.update_yaxes(title_text="品类数值", row=1, col=1, secondary_y=False)
fig.update_yaxes(title_text="成本", row=1, col=1, secondary_y=True)
fig.update_yaxes(title_text="销量", row=2, col=1)
fig.update_xaxes(title_text="日期", row=2, col=1)

fig.update_layout(
    legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1),
    title_text="品类堆叠柱状+成本&销量趋势"
)

# 显示图表
fig.show()

关键注意点

  • 100+列堆叠柱状:Plotly会自动将同位置(row=1,col=1)的bar trace堆叠,无需额外设置。
  • 双Y轴实现:通过secondary_y=True指定绑定右侧Y轴,逻辑和matplotlib的twinx一致。
  • 共享X轴:初始化子图时设置shared_xaxes=True,第二行子图会自动复用第一行X轴,交互时同步缩放/平移。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 16:46:21