3

I have a graph like this: enter image description here

Instead of the days being on top of the symbol, I was wondering if there is a way I can add this annotation between the lines? From one dot to another. I apologize if in case, this is a possible duplicate.

This is my expected output: enter image description here

This is my current code for the annotation:

    fig.add_annotation(
        go.layout.Annotation(
            x=row["order_date"],
            y=row["sales"],
            text=f"{row['time_diff']} days",
            showarrow=False,
            align='center',
            yanchor='auto',
            yshift=10,
            textangle=-0
        )

Any suggestions on how can I do this?

Derek O
  • 16,770
  • 4
  • 24
  • 43

1 Answers1

3

What you can do is create a new dataframe for your annotations by ordering your original df by the order_date, then take the average datetime and average sales between consecutive rows to determine where to place the annotations. To obtain the text, you can take the difference in time between consecutive orders.

Your dataframe for annotations would look something like this:

  time_diff  sales          order_date
0    5 days    5.0 2019-08-27 12:00:00
1   11 days    5.0 2019-09-04 12:00:00
2    0 days    7.5 2019-09-10 00:00:00
3    0 days   15.0 2019-09-10 00:00:00
4    5 days   20.0 2019-09-12 12:00:00
5    0 days   17.5 2019-09-15 00:00:00
6  139 days   15.0 2019-11-23 12:00:00
7       NaT    NaN                 NaT

And here is a figure I made using some sample data similar to yours:

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

## create sample data and figure similar to yours
df = pd.DataFrame({
    'order_date': ['2019-08-25 00:00:00','2019-08-30','2019-09-10','2019-09-10','2019-09-10','2019-09-15','2019-09-15','2020-02-01'],
    'sales': [5,5,5,10,20,20,15,15],
})
df['order_date'] = pd.to_datetime(df['order_date'])

fig = px.line(df, x='order_date', y='sales', markers=True, )
fig.update_traces(marker_color='blue', line_color='darkgrey')

## between consecutive points:
## get the difference in time, and the average sales
df_diff = pd.DataFrame({
    'time_diff': df['order_date'].diff(),
    'sales': (df['sales'] + df['sales'].shift(-1)) / 2,
})

df_diff['order_date'] = df['order_date'] + (df_diff['time_diff'] / 2).shift(-1)
df_diff['time_diff'] = df_diff['time_diff'].shift(-1)

y_axis_range = 1.25*(df.sales.max() - df.sales.min())

fig.add_trace(
    go.Scatter(
        x=df_diff["order_date"],
        y=df_diff["sales"] + 0.01*y_axis_range,
        text=df_diff["time_diff"].astype(str),
        mode='text',
        showlegend=False,
    )
)

fig.show()

enter image description here

Derek O
  • 16,770
  • 4
  • 24
  • 43
  • hey! I have a slight error in this when I try to add `content` column as color and symbol for this. `content` basically has info on what happened to the delivery, sometimes it can be Nan. But when I add it, the colors and symbol don't show up and the graph becomes unconnected – Irene Hawkins Apr 24 '23 at 01:41
  • maybe you can drop any rows where the `content` column is `NaN`? or would you be losing important information? – Derek O Apr 24 '23 at 02:15
  • I tried doing that, somehow it still doesn't join, because I think it is plotting them as different traces, in scatter it connects the dots by a line – Irene Hawkins Apr 24 '23 at 08:26
  • 1
    @IreneHawkins is it possible you could ask this as a separate question? if you can include a sample of your dataframe (with the `content` column) by copying and pasting the output from `df.head(10).to_dict()` in your question, that would be really helpful so I can reproduce the behavior you're seeing – thank you! – Derek O Apr 24 '23 at 14:13
  • Yes!! i have added the issue as a new question over here:https://stackoverflow.com/questions/76093399/line-chart-giving-different-traces-for-color-parameter, thank you so much for helping me figure this out!! – Irene Hawkins Apr 24 '23 at 15:13