I have a multi-line graph that displays percent increase over time. I'd like to set a threshold in my code to have an upper and lower bound. If the line falls outside these bounds, I'd like that specific part of the line graph to be a different color than its parent.
This is what I am doing:
import plotly.express as px
import plotly.graph_objects as go
fig = px.line(df14, x = "Date", y = "Percent", color = "id",
title = "id Growth in Percentage (US)",
labels = {"Percent": "Percent Growth"})
fig.update_layout(
font_family="Arial",
font_color="black",
title_font_family="Arial",
title_font_color="black",
legend_title_font_color="black" #style the text (legend, title etc)
)
fig.update_xaxes(title_font_family="Arial") #style ance center title
fig.update_layout(
title={
'text': "id Growth Percentage in US (Line Graph)",
'y':0.9,
'x':0.5,
'xanchor': 'center',
'yanchor': 'top'})
fig.update_traces(mode='markers+lines') #add dots to line
fig.show()
This is the visual result:
Let me zoom in on one line to better explain:
I would like a threshold set for each id, and if the line goes above or below this threshold, the color will be different for that part of the line graph. For instance:
The upper bound for id IAA may be 5 and the lower bound for IAA may be 0. Any value that is over 5 , or below 0, show be highlighted a specific color.
The upper bound for id SSS may be 10 and the lower bound for SSS may be 3 Any value that is over 10, or below 3, should be highlighted a specific color.
I am wanting the thresholds to be for each id
Please see below:
The highlighted yellow parts of the line reflect where the line graph has exceeded or decreased a set threshold. Is this possible to do this using Plotly?
Here is the raw data example: Updated:
id Start End Diff Percent Date
IAA 4/1/2019 5/1/2019 160.4279 11.10809 04-01-2019 to 05-01-2019
IAA 5/1/2019 6/1/2019 136.0248 8.476798 05-01-2019 to 06-01-2019
IAA 6/1/2019 7/1/2019 174.0513 9.998946 06-01-2019 to 07-01-2019
IAA 7/1/2019 8/1/2019 112.0424 5.851551 07-01-2019 to 08-01-2019
IAA 8/1/2019 9/1/2019 141.8488 6.998691 08-01-2019 to 09-01-2019
IAA 9/1/2019 10/1/2019 103.5522 4.774984 09-01-2019 to 10-01-2019
IAA 10/1/2019 11/1/2019 125.6087 5.528085 10-01-2019 to 11-01-2019
IAA 11/1/2019 12/1/2019 145.2591 6.058016 11-01-2019 to 12-01-2019
IAA 12/1/2019 1/1/2020 115.5121 4.542251 12-01-2019 to 01-01-2020
IAA 1/1/2020 2/1/2020 185.7191 6.985673 01-01-2020 to 02-01-2020
IAA 2/1/2020 3/1/2020 126.7386 4.455896 02-01-2020 to 03-01-2020
IAA 3/1/2020 4/1/2020 231.3461 7.786734 03-01-2020 to 04-01-2020
IAA 4/1/2020 5/1/2020 97.02587 3.02981 04-01-2020 to 05-01-2020
IAA 5/1/2020 6/1/2020 42.85235 1.298792 05-01-2020 to 06-01-2020
IAA 6/1/2020 7/1/2020 124.666 3.729997 06-01-2020 to 07-01-2020
IAA 7/1/2020 8/1/2020 357.9974 10.32609 07-01-2020 to 08-01-2020
IAA 8/1/2020 9/1/2020 490.9587 12.8358 08-01-2020 to 09-01-2020
IAA 9/1/2020 10/1/2020 204.5478 4.739428 09-01-2020 to 10-01-2020
IAA 10/1/2020 11/1/2020 287.6025 6.362292 10-01-2020 to 11-01-2020
SSStest 4/1/2019 5/1/2019 12.38486 5.780551 04-01-2019 to 05-01-2019
SSStest 5/1/2019 6/1/2019 -2.61735 -1.15487 05-01-2019 to 06-01-2019
SSStest 6/1/2019 7/1/2019 -5.6187 -2.50814 06-01-2019 to 07-01-2019
SSStest 7/1/2019 8/1/2019 3.204252 1.467153 07-01-2019 to 08-01-2019
SSStest 8/1/2019 9/1/2019 -25.3782 -11.4521 08-01-2019 to 09-01-2019
SSStest 9/1/2019 10/1/2019 -10.9717 -5.59137 09-01-2019 to 10-01-2019
Any suggestions is appreciated
Update
Is there a way to make the full line display the marker dots on them? I have tried this: mode = 'markers+lines' but did not get the desired result:
**Update, I have figured this out:**
fig.update_traces(mode='markers+lines')
Updated Question:
Also,is there a way to add the Date and Percent titles on the hover annotation here?. I am researching the Plotly docs.
[![enter image description here][4]][4]
I've put together a suggestion that should do exactly what you're asking for. The following figure is produced by the code sample below. The code uses a dictionary that contains the different upper and lower limits for your different PODs along with a possibility to set different colors for different pods:
lim = {'IAD': {'lower': 90,'upper': 350, 'color':'yellow'},
'SJCtest': {'lower': 10,'upper': 12, 'color':'green'}}
I was tempted to filter your dataframe first, and then add new traces to the figure based on that. But my solution actually goes through each datapoint for each trace, and colors the points based on the dictionary above. So no need for any datamunging. Take a look, run a few tests, and let me know how it works out for you.
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
df = pd.DataFrame({'POD': {0: 'IAD',
1: 'IAD',
2: 'IAD',
3: 'IAD',
4: 'IAD',
5: 'IAD',
6: 'IAD',
7: 'IAD',
8: 'IAD',
9: 'IAD',
10: 'IAD',
11: 'IAD',
12: 'IAD',
13: 'IAD',
14: 'IAD',
15: 'IAD',
16: 'IAD',
17: 'IAD',
18: 'IAD',
19: 'SJCtest',
20: 'SJCtest',
21: 'SJCtest',
22: 'SJCtest',
23: 'SJCtest',
24: 'SJCtest'},
'Start': {0: '4/1/2019',
1: '5/1/2019',
2: '6/1/2019',
3: '7/1/2019',
4: '8/1/2019',
5: '9/1/2019',
6: '10/1/2019',
7: '11/1/2019',
8: '12/1/2019',
9: '1/1/2020',
10: '2/1/2020',
11: '3/1/2020',
12: '4/1/2020',
13: '5/1/2020',
14: '6/1/2020',
15: '7/1/2020',
16: '8/1/2020',
17: '9/1/2020',
18: '10/1/2020',
19: '4/1/2019',
20: '5/1/2019',
21: '6/1/2019',
22: '7/1/2019',
23: '8/1/2019',
24: '9/1/2019'},
'End': {0: '5/1/2019',
1: '6/1/2019',
2: '7/1/2019',
3: '8/1/2019',
4: '9/1/2019',
5: '10/1/2019',
6: '11/1/2019',
7: '12/1/2019',
8: '1/1/2020',
9: '2/1/2020',
10: '3/1/2020',
11: '4/1/2020',
12: '5/1/2020',
13: '6/1/2020',
14: '7/1/2020',
15: '8/1/2020',
16: '9/1/2020',
17: '10/1/2020',
18: '11/1/2020',
19: '5/1/2019',
20: '6/1/2019',
21: '7/1/2019',
22: '8/1/2019',
23: '9/1/2019',
24: '10/1/2019'},
'Diff': {0: 160.4279,
1: 136.0248,
2: 174.0513,
3: 112.0424,
4: 141.8488,
5: 103.5522,
6: 125.6087,
7: 145.2591,
8: 115.5121,
9: 185.7191,
10: 126.7386,
11: 231.3461,
12: 97.02587,
13: 42.85235,
14: 124.666,
15: 357.9974,
16: 490.9587,
17: 204.5478,
18: 287.6025,
19: 12.38486,
20: -2.61735,
21: -5.6187,
22: 3.204252,
23: -25.3782,
24: -10.9717},
'Percent': {0: 11.108089999999999,
1: 8.476797999999999,
2: 9.998946,
3: 5.851551000000001,
4: 6.998691,
5: 4.774984,
6: 5.528085,
7: 6.058016,
8: 4.542251,
9: 6.985672999999999,
10: 4.455896,
11: 7.786734,
12: 3.02981,
13: 1.298792,
14: 3.729997,
15: 10.326089999999999,
16: 12.8358,
17: 4.739428,
18: 6.362292,
19: 5.780551,
20: -1.15487,
21: -2.50814,
22: 1.4671530000000002,
23: -11.4521,
24: -5.5913699999999995},
'Date': {0: '04-01-2019 to 05-01-2019',
1: '05-01-2019 to 06-01-2019',
2: '06-01-2019 to 07-01-2019',
3: '07-01-2019 to 08-01-2019',
4: '08-01-2019 to 09-01-2019',
5: '09-01-2019 to 10-01-2019',
6: '10-01-2019 to 11-01-2019',
7: '11-01-2019 to 12-01-2019',
8: '12-01-2019 to 01-01-2020',
9: '01-01-2020 to 02-01-2020',
10: '02-01-2020 to 03-01-2020',
11: '03-01-2020 to 04-01-2020',
12: '04-01-2020 to 05-01-2020',
13: '05-01-2020 to 06-01-2020',
14: '06-01-2020 to 07-01-2020',
15: '07-01-2020 to 08-01-2020',
16: '08-01-2020 to 09-01-2020',
17: '09-01-2020 to 10-01-2020',
18: '10-01-2020 to 11-01-2020',
19: '04-01-2019 to 05-01-2019',
20: '05-01-2019 to 06-01-2019',
21: '06-01-2019 to 07-01-2019',
22: '07-01-2019 to 08-01-2019',
23: '08-01-2019 to 09-01-2019',
24: '09-01-2019 to 10-01-2019'}})
fig = px.line(df, x="Date", y="Diff", color = 'POD')
import plotly.graph_objects as go
included = 0
lim = {'IAD': {'lower': 90,'upper': 350, 'color':'yellow'},
'SJCtest': {'lower': 10,'upper': 12, 'color':'green'}}
for i, d in enumerate(fig.data):
for j, y in enumerate(d.y):
if y < lim[d.name]['lower'] or y > lim[d.name]['upper']:
if j == 0:
fig.add_traces(go.Scatter(x=[fig.data[i]['x'][j]],
y=[fig.data[i]['y'][j]],
mode = 'markers',
marker = dict(color=lim[d.name]['color']),
name = d.name + ' threshold',
legendgroup = d.name + ' threshold'))
included = included + 1
else:
fig.add_traces(go.Scatter(x=[fig.data[i]['x'][j-1], fig.data[i]['x'][j]],
y=[fig.data[i]['y'][j-1], fig.data[i]['y'][j]],
mode = 'lines',
# marker = dict(color='yellow'),
line = dict(width = 6, color = lim[d.name]['color']),
name = d.name + ' threshold',
legendgroup = d.name + ' threshold',
showlegend = False if included > 0 else True,
))
included = included + 1
fig.show()