I am trying to make an interactive PCA plot with Plotly. I am having some troubles in highlighting a certain marker that a user wants to see in the plot.
Instead of highlighting a marker there is a square around it.
My attempt at the code:
from sklearn.datasets import make_blobs
import pandas as pd
import plotly.express as px
X, y = make_blobs(n_samples=30, centers=3, n_features=2,
random_state=0)
ff = PCA(n_components= 2)
clusters = pd.DataFrame(data = ff.fit_transform(X), columns = ['PC1', 'PC2'])
clusters['target'] = y
id = [0, 4, 7]
updatemenus = [dict(buttons=list(dict(label = idd ,method = 'relayout', args = ['shapes', [dict(markers = dict(color = 'Red', size = 120), type = "markers", xref = 'x', yref = 'y', x0 = clusters.loc[idd, 'PC1'], y0=clusters.loc[idd, 'PC2'])]]) for idd in id))]
fig = px.scatter(clusters, x = 'PC1', y = 'PC2', color = 'target', hover_data = ['target'])
fig.update_layout(updatemenus = updatemenus)
fig.show()
What am I doing wrong :)
The shape type
should be one of 'circle' | 'rect' | 'path' | 'line'
, I guess you might want to use 'circle'
instead of 'markers'
.
fig = px.scatter(clusters, x='PC1', y='PC2', color='target', hover_data=['target'])
size = 1/100 # ~1% of the x|y range
rx = (clusters['PC1'].max() - clusters['PC1'].min()) * size
ry = (clusters['PC2'].max() - clusters['PC2'].min()) * size
updatemenus = [dict(
buttons=[dict(
label='None',
method='relayout',
args=['shapes', []]
)] + [dict(
label=idd,
method='relayout',
args=[{
'xaxis.autorange': True,
'yaxis.autorange': True,
'shapes': [{
'type': 'circle',
'layer': 'below',
'xref': 'x',
'yref': 'y',
'x0': clusters.loc[idd, 'PC1'] - rx,
'y0': clusters.loc[idd, 'PC2'] - ry,
'x1': clusters.loc[idd, 'PC1'] + rx,
'y1': clusters.loc[idd, 'PC2'] + ry,
'opacity': 0.3,
'fillcolor': 'red',
'line': {
'color': 'red'
}
}]
}]
) for idd in id]
)]
fig.update_layout(updatemenus=updatemenus)
fig.show()
You could also use a scatter trace dedicated to highlighting instead of using shapes, eg.
fig = px.scatter(clusters, x='PC1', y='PC2', color='target', hover_data=['target'])
fig.add_trace(go.Scatter(
name='highlight',
mode='markers',
showlegend=False,
hoverinfo='skip',
marker=dict(
size=12,
color='red'
)
))
updatemenus = [dict(
buttons=[dict(
label='None',
method='relayout',
args=[{
'x': [clusters['PC1']],
'y': [clusters['PC2']]
}]
)] + [dict(
label=idd,
method='restyle',
args=[{
'x': [clusters['PC1'], [clusters.loc[idd, 'PC1']]],
'y': [clusters['PC2'], [clusters.loc[idd, 'PC2']]]
}]
) for idd in id]
)]
fig.update_layout(updatemenus=updatemenus)
fig.show()