How to fix 'Dropdown Menu Read' Error in Plotly Dash - python-3.x

I have tried to re-create the following example Towards Data Science Example shown on the web
I have written the following code which I modified to this:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
# Step 1. Launch the application
app = dash.Dash()
# Step 2. Import the dataset
filepath = 'https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv'
st = pd.read_csv(filepath)
# range slider options
st['Date'] = pd.to_datetime(st.Date)
dates = ['2015-02-17', '2015-05-17', '2015-08-17', '2015-11-17',
'2016-02-17', '2016-05-17', '2016-08-17', '2016-11-17', '2017-02-17']
features = st.columns[1:-1]
opts = [{'label' : i, 'value' : i} for i in features]
# Step 3. Create a plotly figure
trace_1 = go.Scatter(x = st.Date, y = st['AAPL.High'],
name = 'AAPL HIGH',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
layout = go.Layout(title = 'Time Series Plot',
hovermode = 'closest')
fig = go.Figure(data = [trace_1], layout = layout)
# Step 4. Create a Dash layout
app.layout = html.Div([
# a header and a paragraph
html.Div([
html.H1("This is my first dashboard"),
html.P("Dash is so interesting!!")
],
style = {'padding' : '50px' ,
'backgroundColor' : '#3aaab2'}),
# adding a plot
dcc.Graph(id = 'plot', figure = fig),
# dropdown
html.P([
html.Label("Choose a feature"),
dcc.Dropdown(
id='opt',
options=opts,
value=features[0],
multi=True
),
# range slider
html.P([
html.Label("Time Period"),
dcc.RangeSlider(id = 'slider',
marks = {i : dates[i] for i in range(0, 9)},
min = 0,
max = 8,
value = [1, 7])
], style = {'width' : '80%',
'fontSize' : '20px',
'padding-left' : '100px',
'display': 'inline-block'})
])
])
# Step 5. Add callback functions
#app.callback(Output('plot', 'figure'),
[Input('opt', 'value'),
Input('slider', 'value')])
def update_figure(input1, input2):
# filtering the data
st2 = st[(st.Date > dates[input2[0]]) & (st.Date < dates[input2[1]])]
# updating the plot
trace_1 = go.Scatter(x = st2.Date, y = st2['AAPL.High'],
name = 'AAPL HIGH',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
trace_2 = go.Scatter(x = st2.Date, y = st2[input1],
name = str(input1),
line = dict(width = 2,
color = 'rgb(106, 181, 135)'))
fig = go.Figure(data = [trace_1, trace_2], layout = layout)
return fig
# Step 6. Add the server clause
if __name__ == '__main__':
app.run_server(debug = True)
When I change the feature input, it does not update the plot correctly and does not show the selected features in the plot.
Either there is something wrong with the callback function or the initialization of the graph with the second trace. But I cant figure out where the issue is.

As you are only providing two scatter traces within your callback. From both, one is static for 'AAPL.High'. So you need to limit the dropdown values to Multi=False.
Valid plots are only generated for choosing options like 'AAPL.LOW' and others like dic won't display a second trace. The callback wouldn't terminate if you would keepmulti=True the callback would stil work, if always only one option is selected. The moment you select two or more options the script will fail as it would try to find faulty data for the data return block here:
trace_2 = go.Scatter(x = st2.Date, y = st2[**MULTIINPUT**],
name = str(input1),
line = dict(width = 2,
color = 'rgb(106, 181, 135)'))
Only one column id is allowed to be passed at MULTIINPUT. If you want to introduce more traces please use a for loop.
Change the code to the following:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
# Step 1. Launch the application
app = dash.Dash()
# Step 2. Import the dataset
filepath = 'https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv'
st = pd.read_csv(filepath)
# range slider options
st['Date'] = pd.to_datetime(st.Date)
dates = ['2015-02-17', '2015-05-17', '2015-08-17', '2015-11-17',
'2016-02-17', '2016-05-17', '2016-08-17', '2016-11-17', '2017-02-17']
features = st.columns
opts = [{'label' : i, 'value' : i} for i in features]
# Step 3. Create a plotly figure
trace_1 = go.Scatter(x = st.Date, y = st['AAPL.High'],
name = 'AAPL HIGH',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
layout = go.Layout(title = 'Time Series Plot',
hovermode = 'closest')
fig = go.Figure(data = [trace_1], layout = layout)
# Step 4. Create a Dash layout
app.layout = html.Div([
# a header and a paragraph
html.Div([
html.H1("This is a Test Dashboard"),
html.P("Dash is great!!")
],
style = {'padding' : '50px' ,
'backgroundColor' : '#3aaab2'}),
# adding a plot
dcc.Graph(id = 'plot', figure = fig),
# dropdown
html.P([
html.Label("Choose a feature"),
dcc.Dropdown(
id='opt',
options=opts,
value=features[0],
multi=False
),
# range slider
html.P([
html.Label("Time Period"),
dcc.RangeSlider(id = 'slider',
marks = {i : dates[i] for i in range(0, 9)},
min = 0,
max = 8,
value = [1, 7])
], style = {'width' : '80%',
'fontSize' : '20px',
'padding-left' : '100px',
'display': 'inline-block'})
])
])
# Step 5. Add callback functions
#app.callback(Output('plot', 'figure'),
[Input('opt', 'value'),
Input('slider', 'value')])
def update_figure(input1, input2):
# filtering the data
st2 = st#[(st.Date > dates[input2[0]]) & (st.Date < dates[input2[1]])]
# updating the plot
trace_1 = go.Scatter(x = st2.Date, y = st2['AAPL.High'],
name = 'AAPL HIGH',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
trace_2 = go.Scatter(x = st2.Date, y = st2[input1],
name = str(input1),
line = dict(width = 2,
color = 'rgb(106, 181, 135)'))
fig = go.Figure(data = [trace_1, trace_2], layout = layout)
return fig
# Step 6. Add the server clause
if __name__ == '__main__':
app.run_server(debug = True)
I hope this cleared things up and solved your issues. :)

Related

I am trying to create a population pyramid graph using Dash with Plotly

i have a directory containing three files, years.csv, 2014.csv and 2015.csv. i want to plot a population pyramid graph for the two files but i want pandas to pick the dataframe from the years.csv with respect to the slider value.
my years.csv looks like, on the slider when i select 2014, from the code you can see, its an int that i convert into a string and append .csv to it. but all i want is that final string interpreted as df = pd.read_csv('2014.csv') so that i can be able to generate graphs of all the years as long as that file is in the directoy.
years
0
2014(2014.csv)
1
2015(2015.csv)
from dash import Dash, dcc, html, Input, Output
# import plotly.express as px
import plotly.graph_objects as gp
import pandas as pd
# df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv')
df = pd.read_csv('years.csv')
app = Dash(__name__)
app.layout = html.Div([
dcc.Graph(id='graph-with-slider'),
dcc.Slider(
df['year'].min(),
df['year'].max(),
step=None,
value=df['year'].min(),
marks={str(year): str(year) for year in df['year'].unique()},
id='year-slider'
)
])
#app.callback(
Output('graph-with-slider', 'figure'),
Input('year-slider', 'value'))
def update_figure(selected_year):
new_df = str(df[df.year == selected_year]) + ".csv"
print(new_df)
# fig = px.scatter(filtered_df, x="gdpPercap", y="lifeExp",
# size="pop", color="continent", hover_name="country",
# log_x=True, size_max=55)
y_age = new_df['Age']
x_M = new_df['Male']
x_F = new_df['Female'] * -1
# fig.update_layout(transition_duration=500)
# Creating instance of the figure
fig = gp.Figure()
# Adding Male data to the figure
fig.add_trace(gp.Bar(y= y_age, x = x_M,
name = 'Male',
orientation = 'h'))
# Adding Female data to the figure
fig.add_trace(gp.Bar(y = y_age, x = x_F,
name = 'Female', orientation = 'h'))
# Updating the layoutout for our graph
fig.update_layout(title = 'Population Pyramid of Uganda-2015',
title_font_size = 22, barmode = 'relative',
bargap = 0.0, bargroupgap = 0,
xaxis = dict(tickvals = [-600000, -400000, -200000,
0, 200000, 400000, 600000],
ticktext = ['6k', '4k', '2k', '0',
'2k', '4k', '6k'],
title = 'Population in Thousands',
title_font_size = 14)
)
# fig.show()
return fig
if __name__ == '__main__':
app.run_server(debug=True)

How to update the Figure attributes (x_range) after the Figure is already created using bokeh 1.4, programatticall?

I am trying to create a Bar Chart here, I already have figure object, but want to assign x_range later instead of inside figure object.
I have tried various techniques shown at the end, I am using Bokeh 1.4
def generate_bar_chart(
self, lst_category,lst_frequency, lst_colors, str_xlabel, str_ylabel, str_plot_title,
plot_height=700, plot_width=800, width_bar=0.6):
try:
source = ColumnDataSource(
dict(
x=lst_category,
values=lst_frequency,
color=lst_colors[:len(lst_category)]
)
)
hover_tool = HoverTool(
tooltips=[("Prod Order", "#x"), ("Frequency", "#values")]
)
p = figure(
x_range=lst_category, # I want to set it programatically afterwards, not here
title=str_plot_title,
plot_height=plot_height,
plot_width=plot_width,
background_fill_color="#f9f9f9",
)
p.add_tools(hover_tool)
p.vbar(
x="x",
top="values",
width=width_bar,
source=source,
line_color="#020B13",
)
# p.xgrid.grid_line_color = None
p.y_range.start = 0
p.x_range.range_padding = 0.2
p.xaxis.axis_label = str_xlabel
p.yaxis.axis_label = str_ylabel
p.xaxis.major_label_orientation = 1.1
p.outline_line_color = "#020B13"
p.xaxis.major_label_text_font_size = "11pt"
p.yaxis.major_label_text_font_size = "11pt"
p.yaxis.axis_label_text_font_size = "11pt"
p.xaxis.axis_label_text_font_size = "11pt"
p.yaxis.axis_label_text_font_style = "bold"
p.xaxis.axis_label_text_font_style = "bold"
p.title.text_font_size = "20pt"
show(p)
return True
except Exception as e:
if hasattr(e, "message"):
print(e.message)
else:
print(e)
# I want to do like this
p.x_range = lst_category
# Tried with:
## Not working
p.x_range.factors = lst_category
#
p.x_range=FactorRange(factors=lst_category)
Without a complete minimal reproducer, the best that can be offered is a demonstration of it working on an unrelated, but complete, toy example, which will hopefully be useful as a reference:
from bokeh.io import show
from bokeh.models import ColumnDataSource
from bokeh.models import FactorRange
from bokeh.plotting import figure
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
counts = [5, 3, 4, 2, 4, 6]
source = ColumnDataSource(data=dict(fruits=fruits, counts=counts))
p = figure(plot_height=350, toolbar_location=None, x_range=FactorRange())
p.vbar(x='fruits', top='counts', width=0.9, source=source)
p.xgrid.grid_line_color = None
p.x_range.factors = fruits
p.y_range.start = 0
p.y_range.end = 9
show(p)

How to fix 'Callback Error' in plotly-dash for a Dropdown Menu

I have tried to re-create the following example Towards Data Science Example shown on the web
I have written the following code which I modified to this:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
# Step 1. Launch the application
app = dash.Dash()
# Step 2. Import the dataset
filepath = 'https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv'
st = pd.read_csv(filepath)
# range slider options
st['Date'] = pd.to_datetime(st.Date)
dates = ['2015-02-17', '2015-05-17', '2015-08-17', '2015-11-17',
'2016-02-17', '2016-05-17', '2016-08-17', '2016-11-17', '2017-02-17']
features = st.columns[1:-1]
opts = [{'label' : i, 'value' : i} for i in features]
# Step 3. Create a plotly figure
trace_1 = go.Scatter(x = st.Date, y = st['AAPL.High'],
name = 'AAPL HIGH',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
layout = go.Layout(title = 'Time Series Plot',
hovermode = 'closest')
fig = go.Figure(data = [trace_1], layout = layout)
# Step 4. Create a Dash layout
app.layout = html.Div([
# a header and a paragraph
html.Div([
html.H1("This is a Test Dashboard"),
html.P("Dash is great!!")
],
style = {'padding' : '50px' ,
'backgroundColor' : '#3aaab2'}),
# adding a plot
dcc.Graph(id = 'plot', figure = fig),
# dropdown
html.P([
html.Label("Choose a feature"),
dcc.Dropdown(
id='opt',
options=opts,
value=features[0],
multi=True
),
# range slider
html.P([
html.Label("Time Period"),
dcc.RangeSlider(id = 'slider',
marks = {i : dates[i] for i in range(0, 9)},
min = 0,
max = 8,
value = [1, 7])
], style = {'width' : '80%',
'fontSize' : '20px',
'padding-left' : '100px',
'display': 'inline-block'})
])
])
# Step 5. Add callback functions
#app.callback(Output('plot', 'figure'),
[Input('opt', 'value'),
Input('slider', 'value')])
def update_figure(input1, input2):
# filtering the data
st2 = st[(st.Date > dates[input2[0]]) & (st.Date < dates[input2[1]])]
# updating the plot
trace_1 = go.Scatter(x = st2.Date, y = st2['AAPL.High'],
name = 'AAPL HIGH',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
trace_2 = go.Scatter(x = st2.Date, y = st2[input1],
name = input1,
line = dict(width = 2,
color = 'rgb(106, 181, 135)'))
fig = go.Figure(data = [trace_1, trace_2], layout = layout)
return fig
# Step 6. Add the server clause
if __name__ == '__main__':
app.run_server(debug = True)
It runs and initializes all fine, until I change an input in the dropdown menu. There is a callback error generated, and I can't figure out where it comes from.
The app runs locally and displays the drop down menu fine with all the column, changing the input for the dropdown gives the issue.
The error is as follows:
ValueError:
Invalid value of type 'builtins.list' received for the 'name' property of scatter
Received value: ['AAPL.Open', 'AAPL.Close']
The 'name' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Traceback (most recent call last):
File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "C:\test\Anaconda\lib\site-packages\flask\_compat.py", line 35, in reraise
raise value
File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "C:\test\Anaconda\lib\site-packages\flask\_compat.py", line 35, in reraise
raise value
File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "C:\test\Anaconda\lib\site-packages\flask\app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\test\Anaconda\lib\site-packages\dash\dash.py", line 1152, in dispatch
response.set_data(self.callback_map[output]['callback'](*args))
File "C:\test\Anaconda\lib\site-packages\dash\dash.py", line 1038, in add_context
output_value = func(*args, **kwargs)
File "C:\Users\Dash\Dash\test.py", line 87, in update_figure
color = 'rgb(106, 181, 135)'))
File "C:\test\Anaconda\lib\site-packages\plotly\graph_objs\__init__.py", line 37455, in __init__
self['name'] = name if name is not None else _v
File "C:\test\Anaconda\lib\site-packages\plotly\basedatatypes.py", line 3166, in __setitem__
self._set_prop(prop, value)
File "C:\test\Anaconda\lib\site-packages\plotly\basedatatypes.py", line 3407, in _set_prop
raise err
File "C:\test\Anaconda\lib\site-packages\plotly\basedatatypes.py", line 3402, in _set_prop
val = validator.validate_coerce(val)
File "C:\test\Anaconda\lib\site-packages\_plotly_utils\basevalidators.py", line 1005, in validate_coerce
self.raise_invalid_val(v)
File "C:\test\Anaconda\lib\site-packages\_plotly_utils\basevalidators.py", line 277, in raise_invalid_val
valid_clr_desc=self.description()))
ValueError:
Invalid value of type 'builtins.list' received for the 'name' property of scatter
Received value: ['AAPL.Open', 'AAPL.Close']
The 'name' property is a string and must be specified as:
- A string
- A number that will be converted to a string
Working Code
Your error was in line 85. You can only pass strings or numbers to the name attribute. I just added pythons str() function to transfer input1 to a string. :)
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
import plotly.graph_objs as go
# Step 1. Launch the application
app = dash.Dash()
# Step 2. Import the dataset
filepath = 'https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv'
st = pd.read_csv(filepath)
# range slider options
st['Date'] = pd.to_datetime(st.Date)
dates = ['2015-02-17', '2015-05-17', '2015-08-17', '2015-11-17',
'2016-02-17', '2016-05-17', '2016-08-17', '2016-11-17', '2017-02-17']
features = st.columns[1:-1]
opts = [{'label' : i, 'value' : i} for i in features]
# Step 3. Create a plotly figure
trace_1 = go.Scatter(x = st.Date, y = st['AAPL.High'],
name = 'AAPL HIGH',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
layout = go.Layout(title = 'Time Series Plot',
hovermode = 'closest')
fig = go.Figure(data = [trace_1], layout = layout)
# Step 4. Create a Dash layout
app.layout = html.Div([
# a header and a paragraph
html.Div([
html.H1("This is a Test Dashboard"),
html.P("Dash is great!!")
],
style = {'padding' : '50px' ,
'backgroundColor' : '#3aaab2'}),
# adding a plot
dcc.Graph(id = 'plot', figure = fig),
# dropdown
html.P([
html.Label("Choose a feature"),
dcc.Dropdown(
id='opt',
options=opts,
value=features[0],
multi=True
),
# range slider
html.P([
html.Label("Time Period"),
dcc.RangeSlider(id = 'slider',
marks = {i : dates[i] for i in range(0, 9)},
min = 0,
max = 8,
value = [1, 7])
], style = {'width' : '80%',
'fontSize' : '20px',
'padding-left' : '100px',
'display': 'inline-block'})
])
])
# Step 5. Add callback functions
#app.callback(Output('plot', 'figure'),
[Input('opt', 'value'),
Input('slider', 'value')])
def update_figure(input1, input2):
# filtering the data
st2 = st[(st.Date > dates[input2[0]]) & (st.Date < dates[input2[1]])]
# updating the plot
trace_1 = go.Scatter(x = st2.Date, y = st2['AAPL.High'],
name = 'AAPL HIGH',
line = dict(width = 2,
color = 'rgb(229, 151, 50)'))
trace_2 = go.Scatter(x = st2.Date, y = st2[input1],
name = str(input1),
line = dict(width = 2,
color = 'rgb(106, 181, 135)'))
fig = go.Figure(data = [trace_1, trace_2], layout = layout)
return fig
# Step 6. Add the server clause
if __name__ == '__main__':
app.run_server(debug = True)
Callback error quick fix
Got similar error on callback. Simple dash update resolved it.
pip install dash --upgrade

How do I add vertical moving hover line to my plotly chart

I am trying to achieve what is done here: https://www.quantalys.com/Fonds/120955 with javascript in python plotly. I want to add the hover vertical line and the red annotation on the x axis. I have done some searching on goolgle but I couldn't find the the answer I'm looking for. My current chart looks like this:
trace1 = go.Scatter(
x = df1.x,
y = df1.y,
name = "M&G OPTIMAL INCOME FD EUR AH ACC",
hoverinfo= 'name',
opacity=0.7,
mode = 'lines',
line = dict(
color = ('rgb(2, 12, 245)'),
width = 1,
),
)
trace2 = go.Scatter(
x = df2.x,
y = df2.y,
opacity=0.7,
name = "Alloc Flexible Prudent Monde",
hoverinfo= 'name',
mode = 'lines',
line = dict(
color = ('rgb(67, 45, 24)'),
width = 1,
)
)
trace3 = go.Scatter(
x = df3.x,
y = df3.y,
name = "25% MSCI World + 75% ML Global",
hoverinfo= 'name',
mode = 'lines',
opacity=0.7,
line = dict(
color = ('rgb(205, 12, 24)'),
width = 1,
)
)
layout = go.Layout(
xaxis=dict(
showline=True,
showgrid=True,
showticklabels=True,
linecolor='rgb(204, 204, 204)',
linewidth=2,
mirror=True,
),
yaxis=dict(
showline=True,
showgrid=True,
showticklabels=True,
linecolor='rgb(204, 204, 204)',
linewidth=2,
mirror=True,
),
showlegend=True,
)
data= [trace1, trace2,trace3]
fig = dict(data=data, layout=layout)
iplot(fig, filename='line-mode')
Add this to your layout definition.
showlegend = True,
hovermode = 'x'
Add this to your xaxis definition.
showspikes = True,
spikemode = 'across',
spikesnap = 'cursor',
showline=True,
showgrid=True,
...
And add this to your layout definition:
spikedistance = -1,
xaxis=dict(...
Please refer to this post and the documentation by plotly. :)
EDIT
You ask for the x-axis lable. Please use
spikemode = 'across+toaxis'
Additionally I would suggest to use
spikedash = 'solid'
because it is better fitting your example.

How can I use the plotly dropdown menu feature to update the z value in my choropleth map?

I just want to create a menu on the plot where I'm able to change the z-value in data only. I tried looking at other examples on here: https://plot.ly/python/dropdowns/#restyle-dropdown but it was hard since the examples were not exactly similar to my plot.
import plotly
import plotly.plotly as py
import plotly.graph_objs as go
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv')
data = [go.Choropleth(
locations = df['CODE'],
z = df['GDP (BILLIONS)'],
text = df['COUNTRY'],
colorscale = [
[0, "rgb(5, 10, 172)"],
[0.35, "rgb(40, 60, 190)"],
[0.5, "rgb(70, 100, 245)"],
[0.6, "rgb(90, 120, 245)"],
[0.7, "rgb(106, 137, 247)"],
[1, "rgb(220, 220, 220)"]
],
autocolorscale = False,
reversescale = True,
marker = go.choropleth.Marker(
line = go.choropleth.marker.Line(
color = 'rgb(180,180,180)',
width = 0.5
)),
colorbar = go.choropleth.ColorBar(
tickprefix = '$',
title = 'GDP<br>Billions US$'),
)]
layout = go.Layout(
title = go.layout.Title(
text = '2014 Global GDP'
),
geo = go.layout.Geo(
showframe = False,
showcoastlines = False,
projection = go.layout.geo.Projection(
type = 'equirectangular'
)
),
annotations = [go.layout.Annotation(
x = 0.55,
y = 0.1,
xref = 'paper',
yref = 'paper',
text = 'Source: <a href="https://www.cia.gov/library/publications/the-world-factbook/fields/2195.html">\
CIA World Factbook</a>',
showarrow = False
)]
)
fig = go.Figure(data = data, layout = layout)
py.iplot(fig, filename = 'd3-world-map')
It's been a while since this was asked, but I figured it was still worth answering. I can't speak to how this might have changed since it was asked in 2019, but this works today.
First, I'll provide the code I used to create the new z values and the dropdown menu, then I'll provide all of the code I used to create these graphs in one chunk (easier to cut and paste...and all that).
This is the data I used for the alternate data in the z field.
import plotly.graph_objects as go
import pandas as pd
import random
z2 = df['GDP (BILLIONS)'] * .667 + 12
random.seed(21)
random.shuffle(z2)
df['z2'] = z2 # example as another column in df
print(df.head()) # validate as expected
z3 = df['GDP (BILLIONS)'] * .2 + 1000
random.seed(231)
random.shuffle(z3) # example as a series outside of df
z4 = df['GDP (BILLIONS)']**(1/3) * df['GDP (BILLIONS)']**(1/2)
random.seed(23)
random.shuffle(z4)
z4 = z4.tolist() # example as a basic Python list
To add buttons to change z, you'll add updatemenus to your layout. Each dict() is a separate dropdown option. At a minimum, each button requires a method, a label, and args. These represent what is changing (method for data, layout, or both), what it's called in the dropdown (label), and the new information (the new z in this example).
args for changes to data (where the method is either restyle or update) can also include the trace the change applies to. So if you had a bar chart and a line graph together, you may have a button that only changes the bar graph.
Using the same structure you have:
updatemenus = [go.layout.Updatemenu(
x = 1, xanchor = 'right', y = 1.15, type = "dropdown",
pad = {'t': 5, 'r': 20, 'b': 5, 'l': 30}, # around all buttons (not indiv buttons)
buttons = list([
dict(
args = [{'z': [df['GDP (BILLIONS)']]}], # original data; nest data in []
label = 'Return to the Original z',
method = 'restyle' # restyle is for trace updates
),
dict(
args = [{'z': [df['z2']]}], # nest data in []
label = 'A different z',
method = 'restyle'
),
dict(
args = [{'z': [z3]}], # nest data in []
label = 'How about this z?',
method = 'restyle'
),
dict(
args = [{'z': [z4]}], # nest data in []
label = 'Last option for z',
method = 'restyle'
)])
)]
All code used to create this graph in one chunk (includes code shown above).
import plotly.graph_objs as go
import pandas as pd
import ssl
import random
# to collect data without an error
ssl._create_default_https_context = ssl._create_unverified_context
# data used in plot
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv')
# z values used in buttons
z2 = df['GDP (BILLIONS)'] * .667 + 12
random.seed(21)
random.shuffle(z2)
df['z2'] = z2 # example as another column in the data frame
print(df.head()) # validate as expected
z3 = df['GDP (BILLIONS)'] * .2 + 1000
random.seed(231)
random.shuffle(z3) # example as a series outside of the data frame
z4 = df['GDP (BILLIONS)']**(1/3) * df['GDP (BILLIONS)']**(1/2)
random.seed(23)
random.shuffle(z4)
z4 = z4.tolist() # example as a basic Python list
data = [go.Choropleth(
locations = df['CODE'], z = df['GDP (BILLIONS)'], text = df['COUNTRY'],
colorscale = [
[0, "rgb(5, 10, 172)"],
[0.35, "rgb(40, 60, 190)"],
[0.5, "rgb(70, 100, 245)"],
[0.6, "rgb(90, 120, 245)"],
[0.7, "rgb(106, 137, 247)"],
[1, "rgb(220, 220, 220)"]],
reversescale = True,
marker = go.choropleth.Marker(
line = go.choropleth.marker.Line(
color = 'rgb(180,180,180)', width = 0.5)),
colorbar = go.choropleth.ColorBar(
tickprefix = '$',
title = 'GDP<br>Billions US$',
len = .6) # I added this for aesthetics
)]
layout = go.Layout(
title = go.layout.Title(text = '2014 Global GDP'),
geo = go.layout.Geo(
showframe = False, showcoastlines = False,
projection = go.layout.geo.Projection(
type = 'equirectangular')
),
annotations = [go.layout.Annotation(
x = 0.55, y = 0.1, xref = 'paper', yref = 'paper',
text = 'Source: <a href="https://www.cia.gov/library/publications/the-world-factbook/fields/2195.html">\
CIA World Factbook</a>',
showarrow = False
)],
updatemenus = [go.layout.Updatemenu(
x = 1, xanchor = 'right', y = 1.15, type = "dropdown",
pad = {'t': 5, 'r': 20, 'b': 5, 'l': 30},
buttons = list([
dict(
args = [{'z': [df['GDP (BILLIONS)']]}], # original data; nest data in []
label = 'Return to the Original z',
method = 'restyle' # restyle is for trace updates only
),
dict(
args = [{'z': [df['z2']]}], # nest data in []
label = 'A different z',
method = 'restyle'
),
dict(
args = [{'z': [z3]}], # nest data in []
label = 'How about this z?',
method = 'restyle'
),
dict(
args = [{'z': [z4]}], # nest data in []
label = 'Last option for z',
method = 'restyle'
)])
)]
)
fig = go.Figure(data = data, layout = layout)
fig.show()

Resources