Reputation: 346
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 arg
s 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)
Upvotes: 2
Views: 1785
Reputation: 61094
The code snippet below will produce a Dash App that let's you control the color, symbol and size of your 3D markers using dropdown menus. This is perhaps not perfect for 'size'
, but we can change that if this is otherwise something you can use.
With this setup, the color, sizes and symbol are controlled through:
fig.data[0].update(marker_color=color)
fig.data[0].update(marker_symbol=symbol)
fig.data[0].update(marker_size=size)
And this sweet little detail takes care of the:
This example with ipywidgets works, but it resets the view if plot has been zoomed or rotated.
fig.update_layout(uirevision='constant')
import plotly as py
import pandas as pd
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']
# 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 colors],
value=colors[0]
),
],),
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 [8,10,12,14,16]],
value=8,
),
],)
],
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(),
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("market_graph", "figure"),
[
Input("ctrl_color", "value"),
Input("ctrl_symbol", "value"),
Input("ctrl_size", "value"),
],
)
def history_graph(color, symbol, size):
df = px.data.iris()
fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_width')
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 fig
app.run_server(mode='inline', port = 8007)
Upvotes: 1