使用 add_annotation 对子图进行注释

问题描述 投票:0回答:1

顶部子图工作正常但底部的箭头开始/结束样式与顶部子图不同!

import re
import pandas as pd

import plotly.graph_objects as go
from plotly.subplots import make_subplots

def plot_line(df,pngname):    
    fontsize = 10
    title = "demo"
    xlabel = "KeyPoint"
    ylabel = "Duration(secs)"
    xname = df.columns[0]
    colnames = df.columns[1:]
    
    n = len(colnames)
    
    fig = make_subplots(
        rows=n, cols=1,
        shared_xaxes=True,
        vertical_spacing = 0.02,
    )

    xaxis,yaxis = get_xyaxis()
    for i,yname in enumerate(colnames):        
        trace1 = go.Scatter(
            x=df[xname],
            y=df[yname],
            text=df[yname],
            textposition='top center',
            mode='lines+text',            
            marker=dict(
                size=1,
                line=dict(width=0,color='DarkSlateGrey')),            
            name=yname)
        
        fig.add_trace(
            trace1,
            row=i+1,
            col=1
        )
        fig.update_xaxes(xaxis)
        fig.update_yaxes(yaxis)
        add_anns(fig,df,xname,yname,i+1,1)
                
                            
    xpading=.05
    fig.update_layout(
        margin=dict(l=20,t=40,r=10,b=40),
        plot_bgcolor='#ffffff',#'rgb(12,163,135)',
        paper_bgcolor='#ffffff',        
        title=title,
        title_x=0.5,
        showlegend=True,
        legend=dict(x=.02,y=1.05),        
        barmode='group',
        bargap=0.05,
        bargroupgap=0.0,
        font=dict(
            family="Courier New, monospace",
            size=fontsize,
            color="black"
        ),
    )
    fig.show()
    return

def get_xyaxis():
    xaxis=dict(
        title_standoff=1,
        tickangle=-15,            
        showline=True,
        linecolor='black',
        color='black',
        linewidth=.5,
        ticks='outside',
        showgrid=True,
        gridcolor='grey',
        gridwidth=.5,
        griddash='solid',#'dot',            
    )
    yaxis=dict(
        title_standoff=1,
        showline=True,
        linecolor='black',
        color='black',
        linewidth=.5,            
        showgrid=True,
        gridcolor='grey',
        gridwidth=.5,
        griddash='solid',#'dot',
        zeroline=True,
        zerolinecolor='grey',
        zerolinewidth=.5,
        showticklabels=True,
    )        
    return [xaxis,yaxis]

def add_anns(fig,df,xname,yname,i,j):
    prev = df.loc[0]
    for idx, row in df.iterrows():
        dy = row[yname] - prev[yname]
        x0 = row[xname]
        y0 = row[yname]
        x1 = row[xname]
        y1 = prev[yname]
        if abs(dy) > 0:
            ans = add_vline(fig,x0,y0,y1,i,j,"%.1f"%(dy))
    prev = row    
    return

def add_vline(fig,x0,y0,y1,row,col,text=None):
    dw = 10 # pixels
    if text == None:
        text = "%.1f"%(y1-y0)

    anns = []
    xref='x'
    yref='y'
    fig.add_annotation(#vertical1
        x=x0,y=y0,ax=x0,ay=y1,
        xref=xref,yref=yref,axref=xref,ayref=yref,
        showarrow=True,text='',
        arrowhead=2,arrowside='start+end',arrowsize=2,arrowwidth=.5,arrowcolor='black',
        row=row,col=col,
    )

    fig.add_annotation(# start     
                x=x0,y=y0,ax=-dw,ay=y0,
                xref=xref,yref=yref,axref='pixel',ayref=yref,
                showarrow=True,text='',arrowwidth=.5,arrowcolor='black',                             
        row=row,col=col,
            )

    fig.add_annotation(    
                x=x0,y=y0,ax=dw,ay=y0,
                xref=xref,yref=yref,axref='pixel',ayref=yref,
                showarrow=True,text='',arrowwidth=.5,arrowcolor='black',                             
        row=row,col=col,
            )
    fig.add_annotation( # end
                x=x0,y=y1,ax=-dw,ay=y1,
                xref=xref,yref=yref,axref='pixel',ayref=yref,
                showarrow=True,text='',arrowwidth=.5,arrowcolor='black',                             
        row=row,col=col,
            )
    fig.add_annotation(    
                x=x0,y=y1,ax=dw,ay=y1,
                xref=xref,yref=yref,axref='pixel',ayref=yref,
                showarrow=True,text='',arrowwidth=.5,arrowcolor='black',                             
        row=row,col=col,
            )
    fig.add_annotation(# text label
                x=x0, y=(y0+y1)/2,
                xref=xref,yref=yref,
                text=text,textangle=0,font=dict(color='black',size=14),
                bgcolor='white',
                showarrow=False,arrowhead=1,arrowwidth=2,
        row=row,col=col,
            )
    return

def main():
    data = [
        ['AAA',1,2],
        ['BBB',10,12],
        ['CCC',5,6],
        ['DDD',8,9],
        ]

    df = pd.DataFrame(data,columns=['name','v1','v2'])

    plot_line(df,"./demo.png")
    return
    
main()

输出:

python plotly scatter-plot
1个回答
0
投票

我不确定为什么会这样。似乎要获得两个预期的箭头,我需要指定要引用的每个轴。

def add_vline(fig,x0,y0,y1,row,col,text=None):
    print(row,col)
    dw = 10 # pixels
    if text == None:
        text = "%.1f"%(y1-y0)
    print(text)
    anns = []
    xref='x' if row == 1 else 'x2' # update
    yref='y' if row == 1 else 'y2' # update
    fig.add_annotation(
    ...
    )
© www.soinside.com 2019 - 2024. All rights reserved.