Ananth
Ananth

Reputation: 111

Plotly scatter annotate based on threshold

Consider a table like this -

data = {'Name': {0: 'Alex',
      1: 'Smith',
      2: 'Federico',
      3: 'George',
      4: 'Ram',
      5: 'Helen',
      6: 'Mike',
      7: 'Mark',
      8: 'Alex',
      9: 'Smith',
      10: 'Federico',
      11: 'George',
      12: 'Ram',
      13: 'Helen',
      14: 'Mike',
      15: 'Mark',
      16: 'Alex',
      17: 'Smith',
      18: 'Federico',
      19: 'George',
      20: 'Ram',
      21: 'Helen',
      22: 'Mike',
      23: 'Mark',
      24: 'Alex',
      25: 'Smith',
      26: 'Federico',
      27: 'George',
      28: 'Ram',
      29: 'Helen',
      30: 'Mike',
      31: 'Mark',
      32: 'Alex',
      33: 'Smith',
      34: 'Federico',
      35: 'George',
      36: 'Ram',
      37: 'Helen'},
     'Category': {0: 'A',
      1: 'A',
      2: 'A',
      3: 'A',
      4: 'A',
      5: 'A',
      6: 'A',
      7: 'A',
      8: 'B',
      9: 'B',
      10: 'B',
      11: 'B',
      12: 'B',
      13: 'B',
      14: 'B',
      15: 'B',
      16: 'C',
      17: 'C',
      18: 'C',
      19: 'C',
      20: 'C',
      21: 'C',
      22: 'C',
      23: 'C',
      24: 'D',
      25: 'D',
      26: 'D',
      27: 'D',
      28: 'D',
      29: 'D',
      30: 'D',
      31: 'D',
      32: 'E',
      33: 'E',
      34: 'E',
      35: 'E',
      36: 'E',
      37: 'E'},
     'Value': {0: 125,
      1: 399,
      2: 129,
      3: 147,
      4: 59,
      5: 169,
      6: 94,
      7: 142,
      8: 133,
      9: 54,
      10: 86,
      11: 49,
      12: 49,
      13: 64,
      14: 88,
      15: 65,
      16: 35,
      17: 89,
      18: 72,
      19: 62,
      20: 59,
      21: 198,
      22: 59,
      23: 109,
      24: 147,
      25: 108,
      26: 164,
      27: 110,
      28: 70,
      29: 321,
      30: 256,
      31: 58,
      32: 178,
      33: 121,
      34: 65,
      35: 251,
      36: 204,
      37: 303}}

I have used plotly express to plot a facetted scatter plot where each sub-plot is based on the Category column. One subplot is shown here -

Facet sub plot for category A

How can I add an annotation for ONLY those values that are either above a certain value or max value within that category in plotly express?

My pseudo code is as below -

d = pd.read_csv(fileName.csv)
fig = px.scatter(d[d['Category']=='A'], x="Name", y="Value", facet_col="Category")
fig.update_layout(font_family="Rockwell",
                  template='plotly_dark', title='Values with category A')
fig.update_xaxes(showticklabels=True, visible=True, showgrid=False)
fig.show()

Upvotes: 0

Views: 734

Answers (2)

Heelara
Heelara

Reputation: 979

Since you were interested in annotating the max value, we could use idxmax to get the index of the maximum value and then use annotations to specify the x and y of interest. Based on the provided code, added fig.add_annotation:

fig = px.scatter(df[df['Category']=='A'], x="Name", y="Value", facet_col="Category")
fig.update_layout(font_family="Rockwell",
                  template='plotly_dark', title='Values with category A')
fig.update_xaxes(showticklabels=True, visible=True, showgrid=False)
fig.add_annotation(dict(x=df['Name'][df['Value'].idxmax()],
                        y=df['Value'][df['Value'].idxmax()],
                        showarrow=True,
                        text="Max Value!",
                        xanchor='auto',
                        yanchor='auto'))

fig.show()

And here is the corresponding chart (the yellow circle is simply to highlight the annotation):

enter image description here

Upvotes: 1

r-beginners
r-beginners

Reputation: 35155

Customizing the graph to be composed of expres requires a little ingenuity. I will create a data frame with the maximum value for each category and create the graph in expres as well. I then construct a subplot in the graph object and reuse the graph data from the scatterplot. At the same time, I will add a graph using the graph data for the maximum value. Adjust the position of the annotations and loop the process. Then apply a theme of your choice.

import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go

col = len(df['Category'].unique())
fig = make_subplots(rows=1, cols=col)

fig1 = px.scatter(df, x="Name", y="Value", facet_col="Category")

dfg = df.groupby('Category')[['Name','Value']].max().reset_index()
fig2 = px.scatter(dfg, x='Name', y='Value', text='Value', facet_col='Category')

for i in range(col):
    fig.add_trace(go.Scatter(fig1.data[i]), row=1, col=i+1)
    fig.add_trace(go.Scatter(fig2.data[i]), row=1, col=i+1)
    fig.update_traces(textposition="bottom center")

fig.update_layout(font_family="Rockwell", template='plotly_dark', title='Values with category')
fig.update_xaxes(showticklabels=True, visible=True, showgrid=False)
fig.show()

enter image description here

Upvotes: 1

Related Questions