Search code examples
pythonplotly

how to add annotation of last value in stacked area chart?


I created a stacked area chart using stackgroup= and now I'd like to add annotation to last value.

I am copying the code from here and made some modification.

Plotly: How to annotate end of multiple lines with text and marker colors that match the lines?

this is the original plot for stacked area chart

for ipad,pad in enumerate(pad_list):
    for iwell,well in enumerate(cols_thispad):
        fig.add_scatter(
            x=df.index,
            y=df[well].values, 
            mode='lines',
            line={"color": colors_discrete[iwell]},  #"color": "#035593"
            stackgroup=str(ipad+1), # define stack group
            name=well,
            row=ipad+1,
            col=1,
            legendgroup = str(ipad+1),
            meta=well,
            text=[key.title()+unit_thiskey]*len(df.index),
            hovertemplate='%{meta}<br>Datetime: %{x}<br>%{text}:%{y}<extra></extra>',  
            )

after plotting, I'd like to add annotation to last value of each stacked area chat, here is what I did, if I use stackgroup=, the plot is completely wrong. If I remove stackgroup= in below chat, the last values can be shown and in right chart. However, it is not stacked. so how to show last value markers in stack mode? Thanks

    for i, d in enumerate(fig.data):

        padname=d.name.split('A')[1][:2]
        padname_ix=pad_list.index(padname)
        legendgroup=str(padname_ix+1)
        row=padname_ix+1
        stackgroup=str(padname_ix+1)
             
        fig.add_scatter(x=[d.x[-1]], y = [d.y[-1]],
                        mode = 'markers+text',
                        text = f'{d.y[-1]:.2f}',
                        textfont = dict(color=d.line.color),
                        textposition='middle right',
                        marker = dict(color = d.line.color, size = 12),
                        legendgroup = legendgroup, #d.name,\
                        stackgroup=stackgroup,
                        row=row,col=1,
                        showlegend=False) 

here is the plot without using stackgroup in the 2nd code. It works but not correctly.

enter image description here


Solution

  • Since this function groups stacked graphs, the issue can be resolved by giving each group unit a unique name. In the example answer, the area graph is named 'one' and the text annotation by scatter is named 'two'.

    import yfinance as yf
    ticker = ['AAPL','GOOGL','TSLA','MSFT']
    data = yf.download(ticker, start="2021-01-01", end="2021-03-01")['Close']
    
    import plotly.graph_objects as go
    
    fig = go.Figure()
    for t in data.columns:
        fig.add_trace(go.Scatter(x=data.index,
                                 y=data[t],
                                 hoverinfo='x+y',
                                 mode='lines',
                                 stackgroup='one',
                                 name=t
                                )
                     )
        
        fig.add_trace(go.Scatter(x=[data.index[-1]],
                                 y=[data[t][-1]],
                                 mode='markers+text',
                                 text=round(data[t][-1],2),
                                 textposition='middle left',
                                 stackgroup='two',
                                 name=t,
                                 showlegend=False
                                )
                     )
    fig.update_layout(height=600
                     )
    fig.show()
    

    enter image description here