I'm plotting scattergeo plots on a US map (51 traces for 51 states including DC and 4 traces for 4 different years). I have updatemenus with 2 buttons that switch between one scattergeo with legend (51 traces) and another scattergeo with a slider at the bottom (4 traces). I initially set the 4 traces (years) visible = False
because I wanted only the 51 traces to appear initially but when I click the button to switch to scattergeo with slider and set first 51 traces visible = False
and final 4 traces visible = [True, False, False, False]
none of my traces are visible on the map.
No sure why this is happening. When I set cities_year
visible = True
when first creating the scattergeo (ie they are visible initially) the traces appear but I don't want that because then I have the all my scatterpoints being plotted twice on top of each other.
Here is some code to create dataset:
data = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_us_cities.csv')
data = data.iloc[:400] # Keep only first 400 samples
data.loc[:100, 'year'] = '1990'
data.loc[100:200, 'year'] = '1991'
data.loc[200:300, 'year'] = '1992'
data.loc[300:, 'year'] = '1993'
I am using plotly version 2.7.0 and the offline plotting Here is my plotly code:
cities = []
for state in data['name'].value_counts().index:
data_sub = data.loc[data['name'] == state]
city = dict(
type = 'scattergeo',
visible = True,
locationmode = 'USA-states',
lon = data_sub['lon'],
lat = data_sub['lat'],
mode = 'markers',
marker = dict(
size = 8,
color = "rgb(255, 102, 102)",
opacity = 0.4,
line = dict(
width=0.5,
color='rgb(255, 102, 102)'
)
),
name = state
)
cities.append(city)
cities_year = []
for year in sorted(data.year.value_counts().index):
data_sub = data.loc[data['year'] == year]
city = dict(
type = 'scattergeo',
visible = False,
locationmode = 'USA-states',
lon = data_sub['lon'],
lat = data_sub['lat'],
mode = 'markers',
marker = dict(
size = 8,
color = "rgb(255, 102, 102)",
opacity = 0.4,
line = dict(
width=0.5,
color='rgb(255, 102, 102)'
)
),
name = str(year)
)
cities_year.append(city)
slider = [dict(active = 0,
pad = dict(t = 1),
steps = [dict(args = ["visible", ([False] * len(cities)) + [True, False, False, False]],
label = "1990",
method = "restyle"
),
dict(args = ["visible", ([False] * len(cities)) + [False, True, False, False]],
label = "1991",
method = "restyle"
),
dict(args = ["visible", ([False] * len(cities)) + [False, False, True, False]],
label = "1992",
method = "restyle"
),
dict(args = ["visible", ([False] * len(cities)) + [False, False, False, True]],
label = "1993",
method = "restyle"
)
]
)
]
updatemenus = list([
dict(type="buttons",
active=0,
buttons=list([
dict(label = 'states',
method = 'update',
args = [dict(visible = ([True] * len(cities)) + ([False] * len(cities_year))),
dict(sliders = [],
showlegend = True)]),
dict(label = 'years',
method = 'update',
args = [dict(visible = ([False] * len(cities)) + [True, False, False, False]),
dict(sliders = slider,
showlegend = False)])
]),
)
])
layout = dict(
title = 'myplot',
geo = dict(
scope='usa',
projection=dict(type='albers usa'),
showland=True,
showlakes = True,
landcolor = 'rgb(217, 217, 217)',
subunitwidth=1,
countrywidth=1,
subunitcolor="rgb(255, 255, 255)",
countrycolor="rgb(255, 255, 255)"
),
updatemenus=updatemenus
)
trace_data = cities + cities_year
fig = dict(data=trace_data, layout=layout)
iplot(fig, validate=False)
Problem: If I understand correctly, when the above code
is run: The iplot()
creates the scattergeo()
plot with two buttons labeled ' states
' and ' years
'. Of these two buttons namely the ' states
' button is active and showing its plot (with 'red dots' and legend
). The ' years
' button corresponds to a plot with a slider
option ( years
1990
to 1993
). Now, when this ' years
' button is clicked the expectation is that the 'red dots' should appear across the maps
(for year
1990
). However, this does not happen.
Problem plot with no data points when 'years' button is clicked
Attempted solution:
When visible
is set to True
(below) in city
dictionary
for cities_year
list
of traces
, then the problem is solved. That is after the code
is run the plot appears with two buttons. Now when the ' years
' button
is clicked
, it shows the 'red dots' for the with slider
at the year
1990
. Setting visible=True
may be important because it could be for the very first instance when the plot
is loaded or displayed. ( Jupyter Notebook 5.0.0
; Python 3.6.6
)
cities_year = []
for year in sorted(data.year.value_counts().index):
data_sub = data.loc[data['year'] == year]
city = dict(
type = 'scattergeo',
visible = True,
Now when the 'years' button is clicked the plot is:
Edit - 1 - - - - - - - - - - - - - - - -
The slider
still does not work as expected. However found a work around using just the legends
for selection of year
.
dict(label = 'years',
method = 'restyle',
args = [dict(visible = ([False] * len(cities)) + [True, True, True, True]),
dict(sliders = slider,
showlegend = False)])
Edit - 2 - - - - - - - - - - - - - - - -
Issue is still unresolved, but code below may help narrow down finding the bug. In the code
below, there are two sample data sets for: (1) go.Scatter()
and (2) go.Scattergeo()
. There are only 5
rows
in total in each dataframe
to keep it simple. Note that although the code
for generating the sample data set is different, following the code works to plot both of the above data sets. It shows that the go.Scatter()
works fine, and go.Scattergeo()
has the issue mentioned in the question.
Import libraries
import datetime
from datetime import date
import pandas as pd
import numpy as np
from plotly import __version__
%matplotlib inline
import cufflinks as cf
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
init_notebook_mode(connected=True)
cf.go_offline()
import plotly.offline as pyo
import plotly.graph_objs as go
from plotly.tools import FigureFactory as FF
import json
Create data for go.Scatter()
# Create random numbers
x = np.random.randn(100)
y = 10 + np.random.randn(100)
z = np.linspace(-3,2,100)
df = pd.DataFrame({'x':x, 'y':y, 'z':z})
df.head(2)
# Create traces
trace1 = go.Scatter(visible = True, x=df.x, y=df.y, mode='markers', name='trace1', marker=dict(color='red'))
trace2 = go.Scatter(visible = True, x=df.x, y=df.z, mode='markers', name='trace2', marker=dict(color='black'))
trace3 = go.Scatter(visible = False, x=df.x, y=df.y*df.y, mode='markers', name='trace3', marker=dict(color='blue'))
trace4 = go.Scatter(visible = False, x=df.x, y=df.z*0.5, mode='markers', name='trace4', marker=dict(color='orange'))
trace5 = go.Scatter(visible = False, x=df.x, y=df.z*df.z, mode='markers', name='trace5', marker=dict(color='purple'))
# Create list of traces
data = [trace1, trace2, trace3, trace4, trace5]
Create data for go.Scattergeo()
# Create dataframe for cities
df = pd.DataFrame({'name': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Philadelphia'],
'pop': [8287238, 3826423, 2705627, 2129784, 1539313],
'lat': [40.730599, 34.053717, 41.875555, 29.758938, 39.952335],
'lon': [-73.986581, -118.242727, -87.624421, -95.367697, -75.163789],
'year': [1990, 1991, 1992, 1993, 1991]
})
# Create city traces manually without for-loop
trace1 = go.Scattergeo(visible=True,name = 'trace1',locationmode = 'USA-states',
lon = df[df['name']=='New York']['lon'], lat = df[df['name']=='New York']['lat'],
mode = 'markers',marker = dict(size=10, symbol='circle-open', color = "red"))
trace2 = go.Scattergeo(visible=True,name = 'trace2',locationmode = 'USA-states',
lon = df[df['name']=='Los Angeles']['lon'], lat = df[df['name']=='Los Angeles']['lat'],
mode = 'markers',marker = dict(size=10, symbol='circle-open', color = "red"))
trace3 = go.Scattergeo(visible=False, name = 'trace3', locationmode = 'USA-states',
lon = df[df['year']==1990]['lon'], lat = df[df['year']==1990]['lat'],
mode = 'markers',marker = dict(size=20, symbol='circle-open', color = "blue")
)
trace4 = go.Scattergeo(visible=False, name = 'trace4', locationmode = 'USA-states',
lon = df[df['year']==1991]['lon'], lat = df[df['year']==1991]['lat'],
mode = 'markers',marker = dict(size=20, symbol='circle-open', color = "blue")
)
trace5 = go.Scattergeo(visible=False, name = 'trace5', locationmode = 'USA-states',
lon = df[df['year']==1992]['lon'], lat = df[df['year']==1992]['lat'],
mode = 'markers',marker = dict(size=20, symbol='circle-open', color = "blue")
)
# Create list of traces
data = [trace1, trace2, trace3, trace4, trace5]
Code
below is common to above two data sets
# Create slider
sliders = [dict(active=-1,
pad = {"t": 1},
currentvalue = {"prefix": "Plot Number: "},
execute=True,
steps = [
dict(args = ["visible", [False, False, True, False, False]],
label = "trace3",
method = "restyle"
),
dict(args = ["visible", [False, False, False,True, False]],
label = "trace4",
method = "restyle"
),
dict(args = ["visible", [False, False, False, False, True]],
label = "trace5",
method = "restyle"
)
],
transition = 0
)
]
# Create updatemenus
updatemenus = list([
dict(
buttons= list([
dict(
args = [
{'visible': (True, False, False, False, False)},
{'sliders':[], 'showlegend': True, 'title': 'Plots only'}
],
label = 'single_plot',
method = 'update'
),
dict(
args = [
{'visible': (False, False, True, False, False)},
{'sliders':sliders, 'showlegend': True, 'title': 'Plots with slider'}
],
label = 'multi_plots',
method = 'update'
)
]),
direction = 'left',
pad = {'r': 10, 't': 10},
showactive = True,
type = 'buttons',
x = 0.1,
xanchor = 'left',
y = 1,
yanchor = 'top'
)])
# Create layout
layout = go.Layout(title='Chart') #, geo=dict(scope='usa')) #<--uncomment for Scattergeo() ... optional
layout['updatemenus'] = updatemenus
# Plot data
fig = go.Figure(data=data, layout=layout)
pyo.offline.plot(fig)
Plots with go.Scatter()
(Left: Plot for button
' single_plot
'; Right: plot for button
' multi_plots
')
Note, here the plot on the right-side data points show correctly after pressing 'multi_points' button
.
Plots with go.Scattergeo()
(Left: Plot for button
' single_plot
'; Right: plot for button
' multi_plots
')
Note, here the data points are missing in the plot on the right-side after pressing ' multi_points
' button.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.