I'm trying to make a scatter plot with 2 dropdown menus that select a data column (from a pandas data frame) to be plotted for x and y-axis. I also want the plot to have a correlation stats annotation that change with the dropdown selection, because the annotation is calculated on both the x and y data as parameters. The first part I've managed to do with the code example below, but I am struggling with the annotation.
import pandas as pd
import numpy as np
import plotly.graph_objects as go
# Prep random data
data = pd.DataFrame(dict(
A=np.random.randint(11, size=10),
B=np.random.randint(11, size=10),
C=np.random.randint(11, size=10),
D=np.random.randint(11, size=10)
))
# Create figure and add one scatter trace
fig = go.Figure()
fig.add_trace(go.Scatter(
x=data['A'],
y=data['A'],
visible=True,
mode='markers',
)
)
# Create x and y buttons
x_buttons = []
y_buttons = []
for column in data.columns:
x_buttons.append(dict(method='restyle',
label=column,
args=[{'x': [data[column]]}]
)
)
y_buttons.append(dict(method='restyle',
label=column,
args=[{'y': [data[column]]}]
)
)
# Pass buttons to the updatemenus argument
fig.update_layout(updatemenus=[dict(buttons=x_buttons, direction='up', x=0.5, y=-0.1),
dict(buttons=y_buttons, direction='right', x=-0.01, y=0.5)])
My idea was to first define a function that will take the x and y attributes from the figure data structure (hoping that the dropdown selection change this attributes) and returns the text annotation. Then, based on the plotly reference example, add the annotation to args and change the method of the buttons to 'update'. However, that doesn't seem to be the case and the annotation is static. Anyone has an idea of how I could achieve this? Here is the function and the final code:
from scipy import stats
def corr_annotation(x, y):
pearsonr = stats.pearsonr(x, y)
return 'r = {:.2f} (p = {:.3f})'.format(pearsonr[0], pearsonr[1])
import pandas as pd
import numpy as np
import plotly.graph_objects as go
# Prep random data
data = pd.DataFrame(dict(
A=np.random.randint(11, size=10),
B=np.random.randint(11, size=10),
C=np.random.randint(11, size=10),
D=np.random.randint(11, size=10)
))
# Create figure and add one scatter trace
fig = go.Figure()
fig.add_trace(go.Scatter(
x=data['A'],
y=data['A'],
visible=True,
mode='markers',
)
)
fig.add_annotation(dict(text=corr_annotation(fig['data'][0]['x'], fig['data'][0]['y']),
showarrow=False,
yref='paper', xref='paper',
x=0.99, y=0.95))
# Create x and y buttons
x_buttons = []
y_buttons = []
for column in data.columns:
x_buttons.append(dict(method='update',
label=column,
args=[{'x': [data[column]]},
{'annotations': [dict(text=corr_annotation(fig['data'][0]['x'], fig['data'][0]['y']),
showarrow=False,
yref='paper', xref='paper',
x=0.99, y=0.95)]}]
)
)
y_buttons.append(dict(method='update',
label=column,
args=[{'y': [data[column]]},
{'annotations': [dict(text=corr_annotation(fig['data'][0]['x'], fig['data'][0]['y']),
showarrow=False,
yref='paper', xref='paper',
x=0.99, y=0.95)]}]
)
)
# Pass buttons to the updatemenus argument
fig.update_layout(updatemenus=[dict(buttons=x_buttons, direction='up', x=0.5, y=-0.1),
dict(buttons=y_buttons, direction='right', x=-0.01, y=0.5)])
