Choropleth map showing white page instead of the map - python

I am working on a choropleth map and it is showing a white page instead of the map as shown here
https://i.stack.imgur.com/boYKY.png
I have both the geojson and the excel file downloaded in the same folder.
geojson https://drive.google.com/file/d/1N-rp9yHqE1Rzn2VxoAAweJ8-5XIjk61j/view?usp=sharing
excel https://docs.google.com/spreadsheets/d/1NKeUg20XxJe0jccMgjj9pMxrTIIWeuQk/edit?usp=sharing&ouid=100050178655652050254&rtpof=true&sd=true
Here is my code
import json
import numpy as np
import pandas as pd
import plotly.express as px
df = pd.read_excel('kraje.xlsx', sheet_name='List1')
regions_json = json.load(open("KRAJE.geojson", "r"))
fig = px.choropleth(df,
locations="K_KRAJ",
geojson=regions_json,
color='OB1506')
fig.show()
The console of my browser in which I am viewing the map shows
this
I am using a jupyter notebook in the brave browser.
Can anyone please help me solve this? Thanks
EDIT:
I found the correct geojson file but now I have a different issue. Only one region is colored and not even in the correct color and the rest of the map even outside of my regions is colored in the same color. When I hover over my regions I can see that they are in the correct place but with a wrong color. And I also have no idea why the code colored the whole map and not only the regions from the geojson file. here is an image of the output
new (should be correct) geojson https://drive.google.com/file/d/1S03NX5Q0pqgAsbJnjqt8O5w8gUHH1rt_/view?usp=sharing
import json
import numpy as np
import pandas as pd
import plotly.express as px
df = pd.read_excel('kraje.xlsx', sheet_name='List1')
regions_json = json.load(open("KRAJE.geojson", "r"))
for feature in regions_json['features']:
feature["id"] = feature["properties"]["K_KRAJ"]
fig = px.choropleth(df,
locations="K_KRAJ",
geojson=regions_json,
color='OB1506')
fig.update_geos(fitbounds="locations", visible=False)
fig.show()
SOLUTION
Thanks to Rob Raymond it finally works. There was an issue with the geojson file. I also had a ton of problems installing geopandas and the only tutorial that actually worked was installing each package separately (https://stackoverflow.com/a/69210111/17646343)

there are multiple issues with your geojson
need to define the CRS, it's clearly not epsg:4326. Appears to be UTM CRS for Czech Republic
even with this there are invalid polygons
with valid geojson, a few points you have missed
locations needs to be common across your data frame and geojson
featureidkey needs to be used to define you are joining on name
import json
import numpy as np
import pandas as pd
import plotly.express as px
import geopandas as gpd
files = {
f.suffix: f
for p in ["KRAJE*.*", "KRAJE*.*".lower()]
for f in Path.home().joinpath("Downloads").glob(p)
}
# df = pd.read_excel('kraje.xlsx', sheet_name='List1')
df = pd.read_excel(files[".xlsx"], sheet_name="List1")
# regions_json = json.load(open("KRAJE.geojson", "r"))
regions_json = json.load(open(files[".geojson"], "r"))
regions_json = (
gpd.read_file(files[".geojson"])
.dropna()
.set_crs("EPSG:32633", allow_override=True)
.to_crs("epsg:4326")
.__geo_interface__
)
fig = px.choropleth(
df,
locations="N_KRAJ",
featureidkey="properties.name",
geojson=regions_json,
color="OB1506",
)
fig.update_geos(fitbounds="locations", visible=True)
fig
updated
there are still issues with your geojson. Have fixed it using geopandas and buffer(0) (see Fix invalid polygon in Shapely)
with this and change to plotly parameters I can now generate a figure
import json
import numpy as np
import pandas as pd
import plotly.express as px
import geopandas as gpd
from pathlib import Path
files = {
f.suffix: f
for p in ["KRAJ_*.*", "KRAJE*.*".lower()]
for f in Path.home().joinpath("Downloads").glob(p)
}
# df = pd.read_excel('kraje.xlsx', sheet_name='List1')
df = pd.read_excel(files[".xlsx"], sheet_name="List1")
# regions_json = json.load(open("KRAJE.geojson", "r"))
regions_json = json.load(open(files[".json"], "r"))
# geometry is still invalid!!! force it to valid by buffer(0)
regions_json = gpd.read_file(files[".json"]).assign(geometry=lambda d: d["geometry"].buffer(0)).__geo_interface__
fig = px.choropleth(
df,
locations="K_KRAJ",
featureidkey="properties.K_KRAJ",
geojson=regions_json,
color="OB1506",
)
fig.update_geos(fitbounds="locations", visible=True)
fig

Related

Choropleth maps not showing but white page

I'm trying to make a choropleth figure and below is my sample code:
import json
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
pio.renderers.default='browser'
vietnam_state=json.load(open("diaphantinhenglish.geojson","r"))
df = pd.DataFrame({
'Name': ['Ha Noi','Ha Giang','Cao Bang','Bac Kan','Tuyen Quang'],
'Count': [3757,26,43,27,208]})
#df
Name Count
0 Ha Noi 3757
1 Ha Giang 26
2 Cao Bang 43
3 Bac Kan 27
4 Tuyen Quang 208
fig=px.choropleth(
df,
geojson=vietnam_state,
featureidkey="properties.Name",
locations="Name",
color='Count',
title="ABC",
color_continuous_scale="Aggrnyl")
fig.update_geos(fitbounds="locations",visible=False)
fig.show()
It's worked on my laptop with internet connection as below:
But on my PC without internet connection, maps doesn't show and below is console:
So I would like to ask what should I do. Thanks and best regards.
have amended your code to make it simpler to run (sources geojson and constructs a dataframe for all states)
when I switch off my internet, it still works (if there is a local copy of geojson)
is your PC plotly installation unto date? I'm using 5.3.1
it's maybe a caching issue, can you connect your PC to internet, run. Then go offline. (I have also cleared my caches, still runs)
import requests, json
import pandas as pd
import numpy as np
import plotly.express as px
from pathlib import Path
# fmt: off
f = Path().cwd().joinpath("diaphantinhenglish.geojson")
if not f.exists():
res = requests.get("https://data.opendevelopmentmekong.net/dataset/999c96d8-fae0-4b82-9a2b-e481f6f50e12/resource/2818c2c5-e9c3-440b-a9b8-3029d7298065/download/diaphantinhenglish.geojson")
with open(f, "w") as fh: json.dump(res.json(), fh)
with open(f) as fh: vietnam_state = json.load(fh)
# construct values for all states...
df = pd.DataFrame({"Name": pd.json_normalize(vietnam_state["features"]).loc[:, "properties.Name"].values}
).pipe(lambda d: d.assign(Count=np.random.randint(20, 4000, len(d))))
# fmt: on
fig = px.choropleth(
df,
geojson=vietnam_state,
featureidkey="properties.Name",
locations="Name",
color="Count",
title="ABC",
color_continuous_scale="Aggrnyl",
)
fig.update_geos(fitbounds="locations", visible=False)
fig.show()

Plotly replace x label with image

I have a graph in plotly which I want to replace the x labels.
I pasted this graph as an example. At the bottom you will see ARI, ATL, BAL, etc. I was wondering if its possible to replace these with images? Icons?
same approach that #r-begginers provided in referenced answer
have sourced all logos from kaggle. Used PIL for encoding
have synthesized as an axis by creating a second trace with a -ve percentage and used that plot area to place logos
have set xaxis to invisible so hover provided the team abbreviation
import kaggle.cli
import sys, requests
import pandas as pd
from pathlib import Path
from zipfile import ZipFile
import urllib
import plotly.express as px
from PIL import Image
# fmt: off
# download data set
url = "https://www.kaggle.com/anzhemeng/nfl-team-logos"
sys.argv = [sys.argv[0]] + f"datasets download {urllib.parse.urlparse(url).path[1:]}".split(" ")
kaggle.cli.main()
zfile = ZipFile(f'{urllib.parse.urlparse(url).path.split("/")[-1]}.zip')
# fmt: on
zfile.extractall("nfl-logos")
df = pd.DataFrame(Path.cwd().joinpath("nfl-logos").glob("*.png"), columns=["filename"])
df["team"] = df["filename"].apply(lambda d: d.stem)
df["passResult"] = np.random.uniform(0, 1, len(df))
df = df.sort_values("team")
fig = px.scatter(df, x="team", y="passResult").add_traces(
px.scatter(df, "team", np.full(len(df), -0.05))
.update_traces(marker_color="rgba(0,0,0,0)", hovertemplate="%{x}")
.data
)
for x in fig.data[0].x:
fig.add_layout_image(
source=Image.open(df.loc[df["team"].eq(x), "filename"].values[0]),
x=x,
y=-0.01,
xref="x",
yref="y",
xanchor="center",
sizex=1,
sizey=1,
)
fig.update_layout(xaxis={"visible":False})

My Choropleth map only shows the map, and not the colours

I am new to python and wanted to try using a choropleth map. I have the following code for the graph.
import numpy as np
import pandas as pd
import plotly.express as px
df = pd.read_csv(r'C:\Users\lukee\Desktop\COVID Visualisation\time_series_covid_19_confirmed.csv')
#Data for number of cases for each country across the different dates
geojson = df['Country/Region']
#define the colour codes for the number of cases across the different dates
colourscale = px.colors.sequential.Plasma
#world map to show the intensity of cases in each country
fig = px.choropleth(df,
geojson=geojson,
locationmode= 'country names',
color = df['5/16/21'],
color_continuous_scale = colourscale,
scope='world',
hover_name=df["Country/Region"],
labels={'COVID Cases'})
fig.update(layout_coloraxis_showscale=False)
fig.show()
solution uses sourcing open world, not kaggle
plotting code, there were some inconsistencies on how you requested columns in data frame. addition of featureidkey parameter so dataframe and geojson join correctly
data sourcing
import requests
import pandas as pd
from pathlib import Path
from zipfile import ZipFile
import json, io
# source geojson for country boundaries
geosrc = pd.json_normalize(requests.get("https://pkgstore.datahub.io/core/geo-countries/7/datapackage.json").json()["resources"])
fn = Path(geosrc.loc[geosrc["name"].eq("geo-countries_zip"), "path"].values[0]).name
if not Path.cwd().joinpath(fn).exists():
r = requests.get(geosrc.loc[geosrc["name"].eq("geo-countries_zip"), "path"].values[0],stream=True,)
with open(fn, "wb") as fd:
for chunk in r.iter_content(chunk_size=128):
fd.write(chunk)
zfile = ZipFile(fn)
with zfile.open(zfile.infolist()[0]) as f:
geojson = json.load(f)
# source COVID data
dfall = pd.read_csv(io.StringIO(requests.get("https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/owid-covid-data.csv").text))
dfall["date"] = pd.to_datetime(dfall["date"])
dflatest = (dfall.sort_values(["iso_code", "date"]).groupby("iso_code", as_index=False).last())
colorcol = "new_cases_smoothed_per_million"
# filter out where data is no for a country or no data available for latest date or a big outlier
dflatest = dflatest.loc[
dflatest[colorcol].gt(0).fillna(False)
& dflatest["iso_code"].str.len().eq(3)
& dflatest[colorcol].lt(dflatest[colorcol].quantile(0.97))
]
plotting
import plotly.express as px
#define the colour codes for the number of cases across the different dates
colourscale = px.colors.sequential.Plasma
#world map to show the intensity of cases in each country
fig = px.choropleth(dflatest,
geojson=geojson,
locations= 'iso_code',
featureidkey="properties.ISO_A3",
color = colorcol,
color_continuous_scale = colourscale,
scope='world',
hover_name="location",
labels={colorcol:'COVID Cases'}
)
fig.update_layout(coloraxis_showscale=False, margin={"l":0,"r":0,"t":0,"r":0})
fig
output

Plotly px.choropleth not drawing data from json file

I have a CSV file with the following structure
cardodb_id,CONCELHO,LAT,LONG,DATA,INC 225,Abrantes,39.466667,-8.2,2020-03-25,1000
And a Json file with the following structure:
{"type":"FeatureCollection", "features": [ {"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-8.163874,39.626553],[-8.164286,39.626686],[-8.165384,39.626633],*(more coordinates' pairs)*,[-8.163874,39.626553]]]},"properties":{"cartodb_id":225,"id_2":225,"id_1":16,"id_0":182,"varname_2":null,"nl_name_2":null,"engtype_2":"Municipality","type_2":"Concelho","name_2":"Abrantes","name_1":"Santarém","name_0":"Portugal","iso":"PRT","split_id":"1"}} ]}
Both the CSV and the json file here are part of a larger set but this will do as an example
My code is as follows
import json
with open('abrantes.json') as json_file:
abr = json.load(json_file)
import pandas as pd
df = pd.read_csv("abrantes.csv")
import plotly.express as px
fig = px.choropleth(df, geojson=abr, locations='cardodb_id', color='INC',
color_continuous_scale="Viridis",
range_color=(0, 5000),
labels={'INC':'Incidência'}
)
fig.show()
The end result is an empty map with the scale from 0 to 5000 on the right side, when I was expecting the polygon to be filled with the color correspondent to "INC", i.e., "1000".
What am I doing wrong? Thank you in advance for all the help you can provide.
To draw a map, px.choropleth() must match IDs of your dataframe with IDs of your GeoJSON.
With the parameter locations you specify the column with the IDs in your dataframe.
What you are missing is the parameter featureidkey to specify the same IDs in the GeoJSON. Alternatively, you can omit featureidkey but then the features in your GeoJSON need a parameter id.
Then you have to pay attention to spelling. Your csv file has a column cardodb_id, your GeoJSON a parameter cartodb_id.
And since the polygon you provided is quite small, it is not visible on a world map. Thus, I recommend to add fig.update_geos(fitbounds="locations") to zoom the map to the area of interest.
import json
import pandas as pd
import plotly.express as px
with open('abrantes.json') as json_file:
abr = json.load(json_file)
df = pd.read_csv("abrantes.csv")
fig = px.choropleth(df, geojson=abr, locations='cardodb_id', color='INC',
color_continuous_scale="Viridis",
featureidkey="properties.cartodb_id",
range_color=(0, 5000),
labels={'INC':'Incidência'}
)
fig.update_geos(fitbounds="locations")
fig.show()

Plotly Animated Bar Graph Showing 1 subgroup only in Jupyter

Issue: When I run my code only one status (sub group) shows. The data set is very simple, create date, status and count. I can only think something might be wrong with my data set at this point. Why will it only show one status of the three I have or possibly it works better with a hosted file? It seems to just iterate through the list and not keep each data point in tact until the end. The other code block works fine on github.
Sample of my data set:
Status,Create Date,Count
None,17-Apr-12,8
None,30-Apr-12,9
None,23-Aug-12,10
None,3-Oct-12,11
None,9-Jan-13,12
None,29-Jan-13,13
QBOS,31-Jan-13,1
QBDS,1-Feb-13,1
My code:
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
df = pd.read_csv('qb7.csv')
df.columns = ['Status','Create Date','Count']
includes=['None','QBDS', 'QBOS']
df=df[df['Status'].isin(includes)]
df['Create Date']= pd.to_datetime(df['Create Date']).dt.strftime('%Y-%m-%d')
fig = px.bar(df,
x="Status",
y="Count",
color="Status",
animation_frame="Create Date", hover_name="Status",
range_y=[0,8000])
fig.show()
``
Sample of what I want to make:
import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
df = pd.read_csv('https://raw.githubusercontent.com/shinokada/covid-19-stats/master/data/daily-new-
confirmed-cases-of-covid-19-tests-per-case.csv')
df.columns = ['Country','Code','Date','Confirmed','Days since confirmed']
includes=['United States','Russia', 'India','Brazil']
df=df[df['Country'].isin(includes)]
df['Date']= pd.to_datetime(df['Date']).dt.strftime('%Y-%m-%d')
fig = px.bar(df, x="Country", y="Confirmed", color="Country",
animation_frame="Date", animation_group="Country", range_y=[0,35000])
fig.show()`
I think the reason it doesn't show the intended graph is because of the different number of data. The intended result is achieved when the number of data is aligned.
import pandas as pd
import numpy as np
import io
data = '''
Status,Create Date,Count
None,17-Apr-12,8
None,30-Apr-12,9
None,23-Aug-12,10
None,3-Oct-12,11
None,9-Jan-13,12
None,29-Jan-13,13
QBOS,17-Apr-12,8
QBOS,30-Apr-12,9
QBOS,23-Aug-12,10
QBOS,3-Oct-12,11
QBOS,9-Jan-13,12
QBOS,29-Jan-13,13
QBDS,17-Apr-12,8
QBDS,30-Apr-12,9
QBDS,23-Aug-12,10
QBDS,3-Oct-12,11
QBDS,9-Jan-13,12
QBDS,29-Jan-13,13
'''
df = pd.read_csv(io.StringIO(data), sep=',')
import plotly.graph_objects as go
import plotly.express as px
# df = pd.read_csv('qb7.csv')
df.columns = ['Status','Create Date','Count']
includes=['None','QBDS', 'QBOS']
df=df[df['Status'].isin(includes)]
df['Create Date']= pd.to_datetime(df['Create Date']).dt.strftime('%Y-%m-%d')
fig = px.bar(df,
x="Status",
y="Count",
color="Status",
animation_frame="Create Date", hover_name="Status",
range_y=[0,30])
fig.show()

Categories