简体   繁体   中英

Given the geojson data about districts of an island, how to plot data on a choropleth map at a district-level using Plotly?

Geojson file : Here

Properties of the geojson file :

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 1, 'name_1': 'Agalega', 'hasc_1': 'MU.AG', 'ccn_1': 0, 'cca_1': None, 'type_1': 'Region', 'engtype_1': 'Region', 'nl_name_1': None, 'varname_1': None}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 2, 'name_1': 'Black River', 'hasc_1': 'MU.BL', 'ccn_1': 0, 'cca_1': None, 'type_1': 'District', 'engtype_1': 'District', 'nl_name_1': None, 'varname_1': None}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 3, 'name_1': 'Flacq', 'hasc_1': 'MU.FL', 'ccn_1': 0, 'cca_1': None, 'type_1': 'District', 'engtype_1': 'District', 'nl_name_1': None, 'varname_1': None}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 4, 'name_1': 'Grand Port', 'hasc_1': 'MU.GP', 'ccn_1': 0, 'cca_1': None, 'type_1': 'District', 'engtype_1': 'District', 'nl_name_1': None, 'varname_1': None}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 5, 'name_1': 'Moka', 'hasc_1': 'MU.MO', 'ccn_1': 0, 'cca_1': None, 'type_1': 'District', 'engtype_1': 'District', 'nl_name_1': None, 'varname_1': None}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 6, 'name_1': 'Pamplemousses', 'hasc_1': 'MU.PA', 'ccn_1': 0, 'cca_1': None, 'type_1': 'District', 'engtype_1': 'District', 'nl_name_1': None, 'varname_1': None}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 7, 'name_1': 'Plaines Wilhems', 'hasc_1': 'MU.PW', 'ccn_1': 0, 'cca_1': None, 'type_1': 'District', 'engtype_1': 'District', 'nl_name_1': None, 'varname_1': None}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 8, 'name_1': 'Port Louis', 'hasc_1': 'MU.PL', 'ccn_1': 0, 'cca_1': None, 'type_1': 'District', 'engtype_1': 'District', 'nl_name_1': None, 'varname_1': None}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 9, 'name_1': 'Riviere du Rempart', 'hasc_1': 'MU.RR', 'ccn_1': 0, 'cca_1': None, 'type_1': 'District', 'engtype_1': 'District', 'nl_name_1': None, 'varname_1': None}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 10, 'name_1': 'Rodrigues', 'hasc_1': 'MU.RO', 'ccn_1': 0, 'cca_1': None, 'type_1': 'Autonomous island', 'engtype_1': 'Autonomous island', 'nl_name_1': None, 'varname_1': 'Rodrigues'}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 11, 'name_1': 'Saint Brandon', 'hasc_1': 'MU.CC', 'ccn_1': 0, 'cca_1': None, 'type_1': 'Region', 'engtype_1': 'Region', 'nl_name_1': None, 'varname_1': 'Cargados Carajos)'}

{'id_0': 143, 'iso': 'MUS', 'name_0': 'Mauritius', 'id_1': 12, 'name_1': 'Savanne', 'hasc_1': 'MU.SA', 'ccn_1': 0, 'cca_1': None, 'type_1': 'District', 'engtype_1': 'District', 'nl_name_1': None, 'varname_1': None}

The data to be plotted is in LocationJobCount.csv and tab is used as separator:

             Location  JobCount
0                Moka        55
1          Port Louis        45
2       Pamplemousses        13
3             Savanne         3
4  Riviere du Rempart         8
5         Black River         6
6     Plaines Wilhems       200

My code

"""
Python : 3.9.7
Plotly : 5.8.0
"""
import pandas as pd
import json
import plotly.express as px

districts = json.load(open("stanford-ph377fn8728-geojson.json", 'r'))
df = pd.read_csv("LocationJobCount.csv", sep='\t')

# map each location in dataframe to location in geojson
district_id_map = {}
for feature in districts['features']:
    district_id_map[feature['properties']['name_1']] = feature['properties']['id_1']
df['id'] = df['Location'].apply(lambda x: district_id_map[x])

# create choropleth map
fig = px.choropleth(df, geojson=districts,
                    locations=df['id'],
                    color='JobCount',
                    color_continuous_scale="algae",
                    range_color=[0, max(df['JobCount'])],
                    labels={"Value": "Count"}
                    )
fig.update_layout(geo_scope="world", geo_resolution=50)
# fig.update_geos(fitbounds="locations", visible=False)
fig.show()

After mapping locations between geojson and source file, df looks like this :

             Location  JobCount  id
0                Moka        55   5
1          Port Louis        45   8
2       Pamplemousses        13   6
3             Savanne         3  12
4  Riviere du Rempart         8   9
5         Black River         6   2
6     Plaines Wilhems       200   7

(Location = districts)

Output

After I zoomed in, 在此处输入图像描述

What I tried

  • Reference 1 : I read this post and ensured that the spelling of districts in the geojson file match that in the dataframe.
  • Uncommenting fig.update_geos(fitbounds="locations", visible=False) outputs a white screen.
  • Reference2 : Adding locationmode='country names' as parameter does not do anything.
  • Reference 3 : fig_map.update_layout(geo_scope="africa", geo_resolution=50) does not work because the island Mauritius is not found in this scope.

My goal is to create something similar to this : 在此处输入图像描述

The problem in my previous code is maybe due to a wrong GeoJSON object/data-file pairing.

Solution

In my case, I can directly pair the name_1 property in my GeoJSON file to the Location column in my dataframe. More info : https://plotly.com/python/choropleth-maps/#indexing-by-geojson-properties

import pandas as pd
import json
import plotly.express as px
import plotly.io as pio
pio.renderers.default = 'browser'  # to show geojson map in web browser

districts = json.load(open("stanford-ph377fn8728-geojson.json", 'r'))
df = pd.read_csv("LocationJobCount.csv", sep='\t')

fig = px.choropleth(df, geojson = districts,
                    featureidkey='properties.name_1',
                    locations='Location',  # column in dataframe which contains districts names
                    color='JobCount',  # data from this column in dataframe is plotted
                    color_continuous_scale="algae",
                    )
fig.update_geos(fitbounds="locations") 
fig.show()

This worked but some districts where JobCount is 0 were missing from the map.

I modified my dataframe to include all districts and set 0 as default value :

Location    JobCount
Black River 6
Flacq   0
Grand Port  0
Moka    60
Pamplemousses   17
Port Louis  53
Riviere du Rempart  10
Savanne 3
Plaines Wilhems 233

在此处输入图像描述

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM