Plotly world Choropleth Map offline in python? - python

I'm trying to recreate the world Choropleth map given in plotlys example page here: https://plot.ly/python/choropleth-maps/ with the intention of reusing some of the code, but changing the column which informs the shadings and the labelling.
However when I run the exact code given in the example I receive the following error.
plotly.exceptions.PlotlyError: Because you didn't supply a 'file_id' in the call, we're assuming you're trying to snag a figure from a url. You supplied the url, '', we expected it to start with 'https://plot.ly'.
Run help on this function for more information.
I have no idea where this error arises from and my question really is how do I adapt the code so that it produces the said figure offline? Secondly is there a simple method for saving the figure directly to a png? Apologies if this is trivial I'm completely new to the package.
Here is the code:
import plotly.plotly as py
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv')
data = [dict(
type='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=dict(
line=dict(
color='rgb(180,180,180)',
width=0.5
)),
colorbar=dict(
autotick=False,
tickprefix='$',
title='GDP<br>Billions US$'),
)]
layout = dict(
title='2014 Global GDP<br>Source:\
<a href="https://www.cia.gov/library/publications/the-world-factbook/fields/2195.html">\
CIA World Factbook</a>',
geo=dict(
showframe=False,
showcoastlines=False,
projection=dict(
type='Mercator'
)
)
)
fig = dict(data=data, layout=layout)
py.iplot(fig,validate=False, filename='d3-world-map')

You need to import the offline specific functions, which allow you to plot inline in a jupyter notebook:
import plotly.figure_factory as ff
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected=True)
# All of your code
# ....
# Just change the last line from py.iplot to iplot
iplot(fig,validate=False, filename='d3-world-map')
This renders the image inline in a jupyter notebook, and there's a button that allows you to Download plot as a png in the upper right, along with other functionality.
If you need to save the image as a png, you can try changing the last line to:
plot(fig, validate=False, filename='d3-world-map.html', image='png')
This actually creates an .html file and will open a browser. You can then manually save this as a .png. The last step can be automated with other libraries like selenium, but not sure there is a simple way around it given their documentation:
Note that you must generate the graph and open the file to save the
image.

Related

Chloropleth map using python won't show

I am a new user to Python. I am attempting to create a US county level chloropleth map. To get started I've been reading tutorials on how to do this here . The problem is when I execute the code exactly as it is written in the tutorial, I can't actually see the finished figure. A figure-object is created, but no plot. At the end of the day I am really looking to take this example and apply it to my own data.
Here is the code:
from urllib.request import urlopen
import json
with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
counties = json.load(response)
import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv", dtype={"fips": str})
import plotly.express as px
fig = px.choropleth_mapbox(df, geojson=counties, locations='fips', color='unemp',
color_continuous_scale="Viridis",
range_color=(0, 12),
mapbox_style="carto-positron",
zoom=3, center = {"lat": 37.0902, "lon": -95.7129},
opacity=0.5,
labels={'unemp':'unemployment rate'})
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
In case you are running your code from a standalone script, you can set the default renderer for plotly by adding the following lines at the beginning of your script:
import plotly.io as pio
pio.renderers.default = "browser"
In this case, your default browser will be used as a renderer. Other renders are available (take a look here).
Moreover, if you are running your code in a jupyter notebook, it is enough to have fig as last command of the cell and the figure will be displayed.

Plotly Choropleth map successfully loads in Jupyter, but not Dash browser

I have been able to successfully create a custom shapefile Choropleth map using plotly and geopandas. It loads successfully in my Jupyter window. The following image is what the map looks like when running in Jupyter.
Successfully rendered map in Jupyter
This is the code used to render the above map:
data = go.Choroplethmapbox(
geojson = gdf_json,
locations = df.index.astype(str),
z = df['2016']['Total'],
text = df.index.astype(str),
colorbar=dict(thickness=20,ticklen=3,tickformat=',.2r',outlinewidth=0),
marker_line_width=0.5,
marker_opacity=0.4,
colorscale='gnbu',
zmin=zmin,
zmax=zmax,
hovertemplate = "<b>%{text}</b><br>" +
"%{z:,.4r}<br>" +
"<extra></extra>")
#mapbox geographic map layout
layout = go.Layout(
title='Expenditure, 2020',
autosize=True,
#hovermode='closest',
#showlegend=True,
height=600,
margin=dict(l=0, r=0, t=40, b=0),
mapbox = dict(
domain = {'x': [0, 1],'y': [0, 1]},
center = dict(lat=-27.628296146695863, lon=152.74025612708698),
accesstoken = MAPBOX_ACCESSTOKEN,
#pitch=0,
zoom=10,
style='light')
)
fig = go.Figure(data=data, layout=layout)
fig.show()
However, when I attempt to load the map into Dash, it returns as an empty graph. (Note I cancel out the fig.show() line of code during this process).
app.layout = html.Div([
dcc.Graph(id = 'plot', figure = fig)
])
if __name__ == '__main__':
app.run_server()
Unsuccessful map in Dash
What I have tried
To narrow down the potential problems, I have tried to load in other elements such as dropdowns, radio buttons and a range slider. These loaded successfully, just not the map itself. I am also using the correct public Mapbox API token, as I have previously loaded up a Scattermapbox graph (created a bubble map), which has been successful on Dash.
Possible reasons
Obviously the starting point is whether there might be a very small minor syntax error in my code.
However I'm also wondering if there's something wrong with the loading of the geojson? Even though it loads successfully in Jupyter, maybe there is a slightly different method used when loading it into Dash?
To convert my geopandas polygons into geojson:
I converted it into an appropriate CRS --> gdf.to_crs(epsg=4326)
Set the index to my unique id --> gdf.set_index(id)
Applied this function --> gdf_json = gdf.__geo_interface__
Example of the geojson file
Would love some help if possible. Thank you!
I'm working on a very similar problem and when I converted from jupyter to dash I do not recall having to change the process of the geojson. But don't reject that possibility yet. The fact that it isn't producing any errors from the geojson is likely indicative of an error in how you build your layout. So the first two things you should try first.
Run the debugger (if you aren't already) because this will pick up on errors that will not be ported to your terminal.
app.run_server(debug=True)
Put your map rendering code into a function
def build_map():
return fig #after building the map figure
app.layout = html.Div[(dcc.Graph(figure = build_map())]
I ran into one error with building larger maps where it would time out.
There are so many things that could go wrong here, so process of elimination is key. Feel free to comment below and I will continue to try and help you out!

any workaround to customize plotly multiple time series in python (updated)?

I am trying to customize plotly iplot that rendered multiple time series, but iplot accept only one parameters. I checked into plotly documentation, and usinf go object was mentioned. But I am still not able able to adding custom fonts and watermark to the plotly plot. Can anyone help me out? any possible idea to make this work?
minimal data and demo code
Here is the code that I tried to use for adding custom fonts and watermark on that. I am new to plotly so some fancy built int functions are not quite intuitive to me. Any possible help would be appreciated.
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
from IPython.core.display import display, HTML
import matplotlib as mpl
import cufflinks as cf
import seaborn as sns
import pandas as pd
import numpy as np
# setup
display(HTML("<style>.container { width:35% !important; } .widget-select > select {background-color: gainsboro;}</style>"))
init_notebook_mode(connected=True)
np.random.seed(1)
mpl.rcParams['figure.dpi']= 440
# sample data from cufflinks
df = cf.datagen.lines()
# plotly
iplot([{
'x': df.index,
'y': df[col],
'name': col
} for col in df.columns])
plus, I want to smooth the output of above code (which is multiple time series plot), how can I do that? any idea? Thanks
update
I have done this with matplotlib but don't know doing same thing in plotly. here is my script for loading customized font, watermark:
import matplotib.pyplot as plt
import matplotlib.font_manager as fm
fig, ax = plt.subplots(figsize=(10,6))
fname=r'C:\Users\Nunito-Black.ttf'
myfont=fm.FontProperties(fname=fname,size=50)
legend_fname=r'C:\Users\RobotoCondensed-Regular.ttf'
legend_font=fm.FontProperties(fname=legend_fname,size=20)
## some code for passing plot data to plotting function
ax.text(0.5, 0.5, 'mylogo',fontsize=60,fontproperties=myfont,color='black',
transform=ax.transAxes,ha='center', va='center', alpha=0.3)
plt.show()
how can I do same things in plotly plot? any idea?
Note: This is not (yet) an answer.
I do not understand what do you mean by smooth on the first part. Anyway I see some not necessary imports plus it seems to me you use plotly with an old sintax.
import plotly.graph_objs as go
import cufflinks as cf
import pandas as pd
df = cf.datagen.lines()
fig = go.Figure()
for col in df.columns:
fig.add_trace(
go.Scatter(x=df.index,
y=df[col],
name=col))
fig.show()
The output being
Consider that in this case you could use pd.util.testing.makeTimeDataFrame() instead of import cufflinks.
For the second part i suggest you to read the documentation for go.Layout.font? which is
Supported dict properties:
color
family
HTML font family - the typeface that will be
applied by the web browser. The web browser
will only be able to apply a font if it is
available on the system which it operates.
Provide multiple font families, separated by
commas, to indicate the preference in which to
apply fonts if they aren't available on the
system. The plotly service (at https://plot.ly
or on-premise) generates images on a server,
where only a select number of fonts are
installed and supported. These include "Arial",
"Balto", "Courier New", "Droid Sans",, "Droid
Serif", "Droid Sans Mono", "Gravitas One", "Old
Standard TT", "Open Sans", "Overpass", "PT Sans
Narrow", "Raleway", "Times New Roman".
size
The usage in Python is here and apparently the js version is more flexible see this

Plotly Mapbox images showing blank with blue background (Jupyter Notebook)

I am running the following code to plot points against a city backdrop using Mapbox within Plotly in a Jupyter Notebook, but the plot does not show up, I just get a blue background.
I suspect that I am not using the token correctly?
import plotly.express as px
MBToken = 'pk.[mypublickey]'
px.set_mapbox_access_token(MBToken)
fig = px.scatter_mapbox(dfMaster.dropna()
, lat="latitude"
, lon="longitude"
, color="nta"
, size="count_of_testers"
#, color_continuous_scale=px.colors.cyclical.IceFire
#, size_max=15
#, zoom=10
)
fig.show()
#fig = px.scatter(x='latitude',y='longitude',data_frame=df)
#fig.show()
Running that gives me:
It does not appear to be a Plotly issue, the commented out code creates a scatter plot (although that has the same blue background, but the points show)
Some other posts have pointed to Jupyter offline mode being the possible culprit, but adding this did not resolve
import plotly.offline as pyo
pyo.init_notebook_mode()
Additionally, tried starting up the Jupyter notebook with a higher data rate limit as suggested, but no luck there either
This ended up being a silent data integrity error, as the size field was a string and needed to be converted into numeric

Plotly opens prompt screen after drawing plot

I use the following code to draw a heatmap in plotly:
import plotly.offline as plotly
import plotly.graph_objs as graph_objs
x = []
# fill x with stuff
path = os.path.join(self.get_current_job_directory(), track + '.html')
trace = graph_objs.Heatmap(z = x)
data = [trace]
plotly.plot(data, filename = path)
But I get a prompt screen like this. I need to generate hundreds of such plots on a remote server and its not practical to just dismiss them.
How to get rid of this?
Using the filename argument tells Plotly what filename to use for the HTML file it generates to contain the plot. That file is then viewed in the system's default HTML viewer, which in this case appears to be Lynx. Of course that's rather useless as the point is to view the plot, and Lynx is a text-only Web browser!
To avoid opening the plot, add auto_open=False to your plot() call:
plotly.plot(data, filename=path, auto_open=False)

Categories

Resources