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

Plotly子图添加背景矩形后消除第二子图白边与白区

Plotly子图样式修复方案

问题说明

使用Plotly构建带矩形背景的子图时,遇到两个样式问题:

  • 第二张子图x轴上方存在白色线条
  • 第二张子图y轴附近有未被背景覆盖的白色区域

原实现代码如下:

import pandas as pd

def save_fig(fig,pngname):
    fig.write_image(pngname,format="png",width=600,height=400, scale=1)
    print("[[%s]]"%pngname)
    #fig.show()
    return

from plotly.subplots import make_subplots
import plotly.graph_objects as go
def plot(df1,df2,pngname):
    title = "my title"
    xlabel = "x1"
    ylabel = "y"
    xlabel2 = "x2"
    color = "blue"
    df2 = df2[df2['ts'].diff()>=0]
    fig = make_subplots(
        #x_title=xlabel,
        y_title=ylabel,        
        rows=1, cols=2,
        column_widths=[0.80,0.20],
        row_heights=[1],
        shared_yaxes=True,
        horizontal_spacing=0)

    fig.add_trace(
        go.Scattergl(
            x=df1['name'],
            y=df1['value'],
            error_y=error_bar(df1['value']),
            marker=dict(color=color,size=1),            
            mode='markers'), row=1, col=1)
    update_axis(fig,xlabel,1,1)
    add_bgcolor(fig)
    
    fig.add_trace(
        go.Scattergl(
            x=df2['value'],
            y=df2['ts'],
            error_x=error_bar(df2['value']),
            marker=dict(color=color,size=.1),
            #fill='tozeroy',
            mode='markers'), row=1, col=2)
    update_axis(fig,xlabel2,1,2)
    
    fig.update_layout(
        title_text=title,
        showlegend=False,
        legend=dict(y=1, x=0.1),
        margin=dict(l=40,t=40,r=0,b=0),
        title_x=0.5,
        #title_y=1,        
        paper_bgcolor='white',
        plot_bgcolor='white',
    )
    save_fig(fig,pngname)
    return

def add_bgcolor(fig):
    bgcolor=dict(
        type="rect",
        xref="x2",
        yref="paper",
        x0=0,
        y0=0,
        x1=100,
        y1=1,
        fillcolor="pink",
        opacity=0.5,
        layer="below",
        line_width=0,
    )
    fig.add_shape(bgcolor)
    return

def error_bar(arrayminus):
    error=dict(
        type='data',
        symmetric=False,
        arrayminus=arrayminus,
        array=[0] * len(arrayminus),        
        thickness=5,
        width=0,
    )                
    return error

def update_axis(fig,xlabel,row,col):
    fig.update_xaxes(
        title=xlabel,
        tickangle=25,
        side='bottom',
        showline=True,
        linewidth=.5,
        linecolor='black',
        gridcolor="rgba(38,38,38,0.15)",row=row,col=col
    )
    fig.update_yaxes(
        automargin=True,
        side="left",   
        showline=True,
        linewidth=.5,
        linecolor='black',
        gridcolor="rgba(38,38,38,0.15)",row=row,col=col     
    )        
    return

def main():
    data1 = [
        ['AAA',10],
        ['BBB',20],
        ['CCC',30],
        ['DDD',40],
        ['EEE',50],
        ]
    df1 = pd.DataFrame(data1,columns=['name','value'])
    data2 = [
        [30,10],
        [40,20],
        [50,30],
        [60,40],
        [70,50]
        ]
    df2 = pd.DataFrame(data2,columns=['ts','value'])
    pngname = "/media/sf_work/demo.png"
    plot(df1,df2,pngname)
    return

main()

修复方案

1. 移除第二张子图x轴上方的白色线条

原update_axis函数对所有子图的x轴启用了showline=True,这会同时显示x轴的上下边框。我们需要单独对第二张子图的x轴设置showtop=False,只保留底部轴线:

在调用update_axis(fig,xlabel2,1,2)之后,添加以下代码:

# 隐藏第二张子图x轴顶部的线条
fig.update_xaxes(showtop=False, row=1, col=2)

2. 移除第二张子图y轴附近的白色区域

该区域是因为第二张子图的y轴默认边距导致的,结合shared_yaxes=True,我们可以直接隐藏第二张子图的y轴,同时调整背景矩形的参考系,让它完全覆盖第二张子图的绘图区域:

修改点1:隐藏第二张子图的y轴

同样在调用update_axis(fig,xlabel2,1,2)之后添加:

# 隐藏第二张子图的y轴,消除左侧白色区域
fig.update_yaxes(visible=False, row=1, col=2)

修改点2:调整背景矩形的参考范围

修改add_bgcolor函数,将xref改为domain参考系,确保背景覆盖整个第二张子图的宽度:

def add_bgcolor(fig):
    bgcolor=dict(
        type="rect",
        xref="domain",  # 修改为domain参考系,覆盖第二张子图的整个宽度
        yref="paper",
        x0=0.8,  # 对应column_widths中的0.8,即第二张子图的起始位置
        y0=0,
        x1=1,
        y1=1,
        fillcolor="pink",
        opacity=0.5,
        layer="below",
        line_width=0,
    )
    fig.add_shape(bgcolor)
    return

完整修复后代码

import pandas as pd

def save_fig(fig,pngname):
    fig.write_image(pngname,format="png",width=600,height=400, scale=1)
    print("[[%s]]"%pngname)
    #fig.show()
    return

from plotly.subplots import make_subplots
import plotly.graph_objects as go
def plot(df1,df2,pngname):
    title = "my title"
    xlabel = "x1"
    ylabel = "y"
    xlabel2 = "x2"
    color = "blue"
    df2 = df2[df2['ts'].diff()>=0]
    fig = make_subplots(
        #x_title=xlabel,
        y_title=ylabel,        
        rows=1, cols=2,
        column_widths=[0.80,0.20],
        row_heights=[1],
        shared_yaxes=True,
        horizontal_spacing=0)

    fig.add_trace(
        go.Scattergl(
            x=df1['name'],
            y=df1['value'],
            error_y=error_bar(df1['value']),
            marker=dict(color=color,size=1),            
            mode='markers'), row=1, col=1)
    update_axis(fig,xlabel,1,1)
    add_bgcolor(fig)
    
    fig.add_trace(
        go.Scattergl(
            x=df2['value'],
            y=df2['ts'],
            error_x=error_bar(df2['value']),
            marker=dict(color=color,size=.1),
            #fill='tozeroy',
            mode='markers'), row=1, col=2)
    update_axis(fig,xlabel2,1,2)
    
    # 修复问题1:隐藏第二张子图x轴顶部线条
    fig.update_xaxes(showtop=False, row=1, col=2)
    # 修复问题2:隐藏第二张子图y轴,消除左侧白色区域
    fig.update_yaxes(visible=False, row=1, col=2)
    
    fig.update_layout(
        title_text=title,
        showlegend=False,
        legend=dict(y=1, x=0.1),
        margin=dict(l=40,t=40,r=0,b=0),
        title_x=0.5,
        #title_y=1,        
        paper_bgcolor='white',
        plot_bgcolor='white',
    )
    save_fig(fig,pngname)
    return

def add_bgcolor(fig):
    bgcolor=dict(
        type="rect",
        xref="domain",  # 修改为domain参考系,覆盖第二张子图整个宽度
        yref="paper",
        x0=0.8,  # 对应column_widths的0.8,第二张子图起始位置
        y0=0,
        x1=1,
        y1=1,
        fillcolor="pink",
        opacity=0.5,
        layer="below",
        line_width=0,
    )
    fig.add_shape(bgcolor)
    return

def error_bar(arrayminus):
    error=dict(
        type='data',
        symmetric=False,
        arrayminus=arrayminus,
        array=[0] * len(arrayminus),        
        thickness=5,
        width=0,
    )                
    return error

def update_axis(fig,xlabel,row,col):
    fig.update_xaxes(
        title=xlabel,
        tickangle=25,
        side='bottom',
        showline=True,
        linewidth=.5,
        linecolor='black',
        gridcolor="rgba(38,38,38,0.15)",row=row,col=col
    )
    fig.update_yaxes(
        automargin=True,
        side="left",   
        showline=True,
        linewidth=.5,
        linecolor='black',
        gridcolor="rgba(38,38,38,0.15)",row=row,col=col     
    )        
    return

def main():
    data1 = [
        ['AAA',10],
        ['BBB',20],
        ['CCC',30],
        ['DDD',40],
        ['EEE',50],
        ]
    df1 = pd.DataFrame(data1,columns=['name','value'])
    data2 = [
        [30,10],
        [40,20],
        [50,30],
        [60,40],
        [70,50]
        ]
    df2 = pd.DataFrame(data2,columns=['ts','value'])
    pngname = "/media/sf_work/demo.png"
    plot(df1,df2,pngname)
    return

main()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 04:37:13