John Conor
John Conor

Reputation: 884

Add Polynomial Trend Line Plotly [PYTHON]

I'm trying to add a polynomial trend line to a plotly go chart with 2 y axes, the trend line should follow the trace charting the weekly column against time.

The purpose of the chart is to look at an outcome over time and identify the inflection in the dataset when a new variable is introduced.

Dataset:

date  weekly partially fully
3/28/20     2   0   0
4/4/20      5   0   0
4/11/20     3   0   0
4/18/20     6   0   0
4/25/20     2   0   0
5/2/20      3   0   0
5/9/20      5   0   0
5/16/20     1   0   0
5/23/20     0   0   0
5/30/20     2   0   0
6/6/20      2   0   0
6/13/20     0   0   0
6/20/20     0   0   0
6/27/20     0   0   0
7/4/20      0   0   0
7/11/20     0   0   0
7/18/20     0   0   0
7/25/20     1   0   0
8/1/20      0   0   0
8/8/20      0   0   0
8/15/20     0   0   0
8/22/20     1   0   0
8/29/20     1   0   0
9/5/20      1   0   0
9/12/20     0   0   0
9/19/20     0   0   0
9/26/20     0   0   0
10/3/20     0   0   0
10/10/20    0   0   0
10/17/20    0   0   0
10/24/20    4   0   0
10/31/20    4   0   0
11/7/20     15  0   0
11/14/20    6   0   0
11/21/20    2   0   0
11/28/20    1   0   0
12/5/20     4   0   0
12/12/20    4   0   0
12/19/20    7   0   0
12/26/20    0   0   0
1/2/21      7   406 0
1/9/21      5   406 0
1/16/21     11  406 0
1/23/21     8   242 395
1/30/21     2   241 396
2/6/21      5   241 396
2/13/21     4   22  615
2/20/21     6   81  625
2/27/21     2   98  625
3/6/21      3   98  625
3/13/21     1   98  625
3/20/21     2   85  693
3/27/21     5   84  709
4/3/21      5   84  710
4/10/21     2   84  760
4/17/21     3   31  849

I know this can be done with plotly express but it does not support dual axes from what I can find, which I require due to the order of magnitude difference in the values.

All of the supporting material I have came across in my frivolous google search so far has been highly complicated for something that I know is incredibly simple in spreadsheet packages such as excel.

Here is my code so far:

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

# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])

# Add traces

fig.add_trace(go.Scatter(x=df['date'], y=df['full'], name="Indicator 2",line=dict(color="Green"),opacity=0.01,fill='tozeroy',), secondary_y=True,)

fig.add_trace(go.Scatter(x=df['date'], y=df['weekly'], name="Weekly",line=dict(color="Red")),secondary_y=False,)

# Add figure title
fig.update_layout(
    title_text="Change over Time",width = 1200, height = 600)

# Set x-axis title
fig.update_xaxes(title_text="xaxis title")

# Set y-axes titles
fig.update_yaxes(title_text="<b>primary</b> yaxis1", secondary_y=False)
fig.update_yaxes(title_text="<b>secondary</b> yaxis2", secondary_y=True)

fig.show()

This is the current graph output:

enter image description here

Much obliged.

Upvotes: 3

Views: 1922

Answers (1)

Rob Raymond
Rob Raymond

Reputation: 31166

  • have synthesized data similar to the data that cannot be used without OCR
  • you can calculate the polynomial using numpy then just plot another line
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np

d = pd.date_range("28-mar-2020", freq="W", periods=60)
df = pd.DataFrame({"date":d, "weekly":np.random.randint(0,15,len(d)), "partial":np.random.randint(31,406,len(d)),
              "full":np.random.randint(395,850,len(d))
             }).assign(partial=lambda x: np.where(x.date.dt.year<2021,0, x.partial),
                      full=lambda x: np.where(x.date.lt("1-Feb-2021"),0, x.full))


df["smooth"] = np.polyval(np.polyfit(df["date"].astype(int),df["weekly"], 5), df["date"].astype(int))

# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])

# Add traces

fig.add_trace(go.Scatter(x=df['date'], y=df['full'], name="Indicator 2",line=dict(color="Green"),opacity=0.01,fill='tozeroy',), secondary_y=True,)

fig.add_trace(go.Scatter(x=df['date'], y=df['weekly'], name="Weekly",line=dict(color="Red")),secondary_y=False,)
fig.add_trace(go.Scatter(x=df['date'], y=df['smooth'], name="Smooth",line=dict(color="Blue")),secondary_y=False,)


# Add figure title
fig.update_layout(
    title_text="Change over Time",width = 1200, height = 600)

# Set x-axis title
fig.update_xaxes(title_text="xaxis title")

# Set y-axes titles
fig.update_yaxes(title_text="<b>primary</b> yaxis1", secondary_y=False)
fig.update_yaxes(title_text="<b>secondary</b> yaxis2", secondary_y=True)

enter image description here

Upvotes: 4

Related Questions