I’m trying to use the built in plotly widgets to select values for marker size and color in scatter and scatter_3d from plotly express. I can get this working using ipywidgets but then it resets the plot to the original orientation (3D). But when using updatemenus instead nothing changes at all.
Here’s an example code:
import plotly.express as px
df = px.data.iris()
fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width',
color='species', size='petal_length' ,text='species_id' )
fig.update_layout(scene_aspectmode='data')
fig.update_layout(updatemenus=[
dict(
buttons=list([
dict(
args=['size','sepal_length'],
label='sepal length',
method='update'
),
dict(
args=['size','sepal_width'],
label='sepal width',
method='update'
)
]),
showactive=True,
)
])
fig.show()
I’ve tried a number of variations to args and different methods.
This example with ipywidgets works, but it resets the view if plot has been zoomed or rotated.
import plotly.express as px
import ipywidgets as widgets
from ipywidgets import interactive, interact, interact_manual, Layout
df = px.data.iris()
sel_size= widgets.Dropdown(
options=sorted(df.columns),
description='Size',
value='sepal_length'
)
sel_colour= widgets.Dropdown(
options=sorted(df.columns),
description='Colour',
value='species'
)
@interact
def get_column(size=sel_size,color=sel_colour):
scatter3D_fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width',
color='species', size='petal_length' ,text='species_id',opacity=0.5)
scatter3D_fig.update_layout(scene_aspectmode='data')
scatter3D_fig.show()
Modified from @vestland's answer this is close to what I want. I can select different data for marker size and color, without changing the camera/eye position. Although when I select a categorical variable for color, changing the marker symbol only changes them for one category.
from plotly import tools
import plotly.express as px
import plotly.graph_objects as go
import dash
import dash_core_components as dcc
import dash_html_components as html
from jupyter_dash import JupyterDash
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
app = JupyterDash(external_stylesheets=[dbc.themes.SLATE])
# colors = px.colors.qualitative.Plotly
colors = ['blue', 'green', 'red', 'black', 'yellow']
symbols = ['circle', 'circle-open', 'square', 'square-open', 'diamond', 'diamond-open', 'cross', 'x']
columns = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species', 'species_id']
# Set up well organized controls in a dbc.Card()
controls = dbc.Card([dbc.FormGroup([dbc.Label("Color"),
dcc.Dropdown(id='ctrl_color',
options= [{'label': k, 'value': k} for k in columns],
# value=colors[0]
value='species'
),
],),
dbc.FormGroup([dbc.Label("Symbol"),
dcc.Dropdown(id='ctrl_symbol',
options=[{'label': k, 'value': k} for k in symbols],
value=symbols[0],
),
],),
dbc.FormGroup([dbc.Label("Size"),
dcc.Dropdown(id='ctrl_size',
options=[{'label': k, 'value': k} for k in columns],
value='petal_length',
),
],)
],
body=True,
style = {'font-size': 'large'}
)
# Set up the app layout using dbc.Container(), dbc.Row(), and dbc.Col()
app.layout = dbc.Container([html.H1("Marker color, symbol and size"),
html.Hr(),
html.Div(id="campos"),
dbc.Row([dbc.Col([controls],xs = 4),
dbc.Col([dbc.Row([dbc.Col(dcc.Graph(id="market_graph")),])]),
]),
html.Br(),
],
fluid=True,
)
# 3D figure with callbacks for color, symbol and size
@app.callback(
[Output("campos", "children"),Output("market_graph", "figure")],
[
Input("market_graph", "relayoutData"),
Input("ctrl_color", "value"),
Input("ctrl_symbol", "value"),
Input("ctrl_size", "value"),
],
)
def history_graph(data,color, symbol, size):
df = px.data.iris()
fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width',size=size,color=color)
# fig.data[0].update(marker_color=color)
fig.data[0].update(marker_symbol=symbol)
# fig.data[0].update(marker_size=size)
fig.update_layout(uirevision='constant')
fig.update_layout(template = 'plotly_dark')
return str(data),fig
app.run_server(mode='inline', port = 8008)

