问题
I've created a Choropleth map and I want to know if it's possible to add a drop down with each state. When you select the drop down the graph changes to a line graph of the number of Bachelor degrees earned over time in that state.
A sample of my data:
year state statetotal ba_total
0 1984.0 AK 221.0 108.0
1 1985.0 AK 242.0 141.0
2 1984.0 NC 229.0 117.0
3 1985.0 NC 257.0 138.0
4 1984.0 MA 272.0 165.0
5 1985.0 MA 280.0 176.0
6 1984.0 NY 375.0 249.0
7 1985.0 NY 309.0 208.0
This is what I've tried so far:
for col in df.columns:
df[col] = df[col].astype(str)
scl = [[0.0, 'rgb(242,240,247)'],[0.2, 'rgb(218,218,235)'],[0.4, 'rgb(188,189,220)'],\
[0.6, 'rgb(158,154,200)'],[0.8, 'rgb(117,107,177)'],[1.0, 'rgb(84,39,143)']]
df['text'] = df['statename'] + '<br>' + \
'Bachelor '+df['ba_total']+'<br>'+ \
'Master '+df['ma_total']+'<br>'+ \
'PhD '+df['phd_total']
# Years
years = list(df['year'].astype(float).astype(int).unique())
# make data
data = []
# Append data
for year in years:
dataset_by_year = df[df['year'].astype(float).astype(int) == int(year)]
data_dict = [ dict(
type='choropleth',
visible=True,
colorscale = scl,
autocolorscale = False,
locations = dataset_by_year['state'],
z = dataset_by_year['statetotal'].astype(float),
locationmode = 'USA-states',
text = dataset_by_year['text'],
marker = dict(
line = dict (
color = 'rgb(255,255,255)',
width = 2
) ),
colorbar = dict(
title = "Educ. Grads")
) ]
data.append(data_dict[0])
# let's create the steps for the slider
steps = []
for i in range(len(data)):
step = dict(method='restyle',
args=['visible', [False] * len(data)],
label='{}'.format(i + 1984))
step['args'][1][i] = True
steps.append(step)
sliders = [dict(active=0,
pad={"t": 1},
steps=steps)]
# create the empty dropdown menu
updatemenus = list([dict(buttons=list()),
dict(direction='down',
showactive=True)])
total_codes = len(df.state.unique()) + 1
for s, state in enumerate(df.state.unique()):
# add a trace for each state
data.append(dict(type='scatter',
x=[i for i in range(1984, 2016)],
y=[i for i in df.statetotal],
visible=False))
# add each state to the dropdown
visible_traces = [False] * total_codes
visible_traces[s + 1] = True
updatemenus[0]['buttons'].append(dict(args=[{'visible': visible_traces}],
label=state,
method='update'))
# add a dropdown entry to reset the map
updatemenus[0]['buttons'].append(dict(args=[{'visible': [True] + [False] * (total_codes - 1)}],
label='Map',
method='update'))
layout = dict(title='Aggregated Number of Graduates in Education by State',
updatemenus=updatemenus,
geo=dict(scope='usa',
projection={'type': 'albers usa'}),
sliders=sliders)
fig = dict(data=data,
layout=layout)
I'm getting an AttributeError
related to the function I've created but previously I managed to generate the graph with the menus present but the graph generated 50 menu buttons rather than a drop down with 50 options.
I think these issues can be resolved but the crux of my problems are whether or not it's possible to combine graph types together? Ideally I'd want to show a line graph if I click on Alaska showing the number of bachelor's degrees completed over the time period observed. Is this possible?
EDIT Code
I managed to get the drop down menu to work but it doesn't mesh well with the slider and the map. I don't know how to get slider to disappear when you click an item in the drop down menu or how to prevent the map from being overlayed on top of the line graph.
回答1:
You can get the desired functionality with Plotly online but all the data needs to be loaded when the first graph is rendered. Perhaps have a look at Plotly's Dash which enabled dynamic loading of data.
In order to get the dropmenu which shows traces you could do the following:
- First create map, then add a scatter plot for each country but only show the map by setting the
visible
attribute. - Create a drop down menu which shows the scatter plot for the selected country (by passing an array of Booleans to
visible
) - Add a menu entry to show the map again
import pandas as pd
import plotly
plotly.offline.init_notebook_mode()
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2011_us_ag_exports.csv')
# create the initial map
data = [dict(type='choropleth',
locations = df['code'].astype(str),
z=df['total exports'].astype(float),
locationmode='USA-states',
visible=True)]
layout = dict(geo=dict(scope='usa',
projection={'type': 'albers usa'}))
# create the empty dropdown menu
updatemenus = list([dict(buttons=list()),
dict(direction='down',
showactive=True)])
total_codes = len(df.code.unique()) + 1
for s, state in enumerate(df.code.unique()):
# add a trace for each state
data.append(dict(type='scatter',
x=[i for i in range(1980, 2016)],
y=[i + random.random() * 100 for i in range(1980, 2016)],
visible=False))
# add each state to the dropdown
visible_traces = [False] * total_codes
visible_traces[s + 1] = True
updatemenus[0]['buttons'].append(dict(args=[{'visible': visible_traces}],
label=state,
method='update'))
# add a dropdown entry to reset the map
updatemenus[0]['buttons'].append(dict(args=[{'visible': [True] + [False] * (total_codes - 1)}],
label='Map',
method='update'))
layout['updatemenus'] = updatemenus
fig = dict(data=data,
layout=layout)
plotly.offline.iplot(fig)
来源:https://stackoverflow.com/questions/46818391/adding-drop-down-menu-to-choropleth-map-to-select-each-state-and-generate-new-gr