Search code examples
pythonpandasdatetimeplotlyscatter-plot

Setting boundaries for datetime x axis on Plotly (Python)


I have to plot some chronologically-ordered values (one value per month, in my case) on a Plotly (Python) graph. Also, I have to add a "end of period label" (i.e. a marker with text indicating the last value of the series) that has to be positioned at 'middle right'.

A working example would be something like this:

import pandas as pd
import numpy as np
import plotly.graph_objects as go

date_range = pd.to_datetime(pd.date_range(start='1/1/2013', end='9/1/2022', freq='M').tolist()).date
values = np.random.randint(100, size=len(date_range)).tolist()
fig = go.Figure(
)

fig.add_trace(go.Scatter(
    showlegend=False,
    x=date_range,
    y=values,
    mode='lines',
    line=dict(
        width=2,
        color="red",
        )
    )
)

fig.add_trace(go.Scatter(
    showlegend=False,
    x=[date_range[-1]],
    y=[values[-1]],
    text=[values[-1]],
    textposition='middle right',
    texttemplate="%{text:.3f}",
    mode='markers+text',
    line=dict(
        width=2,
        color="red",
        )
    )
)

fig.update_layout(
    xaxis=dict(
        tickformat="%m\n<b>%Y", dtick="M3",
        )
)

which produces the following plot:Plot for StackOverflow

I am facing the following problem: the end of period label "extends" beyond the last value of the date range and makes the x axis go into the green area, which are all undesired months (for example, those that extend beyond the last value of the date range and into 2023).

I tried several things to "erase" or delete that undesired part of the x axis, but nothing worked properly: either the end of period label was cut in half or the whole x axis disappeared.

Thank you in advance for any help or suggestion.


Solution

    • as per @r0beginners comments
    • given text is outside graph area use an annotation for the text
    • make marker scatter just mode=markers
    • explicitly state xaxis range range=date_range[[0,-1]]
    import pandas as pd
    import numpy as np
    import plotly.graph_objects as go
    
    date_range = pd.to_datetime(
        pd.date_range(start="1/1/2013", end="9/1/2022", freq="M").tolist()
    ).date
    values = np.random.randint(100, size=len(date_range)).tolist()
    fig = go.Figure()
    
    fig.add_trace(
        go.Scatter(
            showlegend=False,
            x=date_range,
            y=values,
            mode="lines",
            line=dict(
                width=2,
                color="red",
            ),
        )
    )
    
    
    fig.add_trace(go.Scatter(
        showlegend=False,
        x=[date_range[-1]],
        y=[values[-1]],
        mode='markers',
        marker_size=15
        )
    )
    
    fig.add_annotation(
        x = date_range[-1],
        y = values[-1],
        text = values[-1],
        xshift=10,
        yshift=0,
        showarrow=False
    )
    
    
    fig.update_layout(
        xaxis=dict(
            tickformat="%m\n<b>%Y",
            dtick="M3",
            range=date_range[[0,-1]]
        )
    )
    

    enter image description here