How to make Choropleth map about Covid-19 Cases in New Zealand


Import the packages

from lxml.html import parse
from urllib.request import urlopen
from pandas.io.parsers import TextParser
import pandas as pd
from pandas import DataFrame, Series
import numpy as np
import folium

Get the cases data for mapping

Define the function to parse the table data from website
def parse_options_data(table):
    rows = table.findall('.//tr') # read out all the content in the table
    header = _unpack(rows[0], kind='th') # read out the header of the table
    data = [_unpack(r) for r in rows[1:]]  # read out the table
    return TextParser(data, names=header).get_chunk()
#reterive the Confirmed Covid-19 cases data from Health of Ministry website
url = 'https://www.health.govt.nz/our-work/diseases-and-conditions/covid-19-novel-coronavirus/covid-19-current-cases'
parsed = parse(urlopen(url))
doc = parsed.getroot()
tables = doc.findall('.//table') # to select all the tables on the target website
calls = tables[1] # select the target table
call_data = parse_options_data(calls)
df = DataFrame(call_data)# put the data into pandas dataframe
df.head()
DHB Number of cases Change in last 24 hours
0 Auckland 180 4
1 Bay of Plenty 41 0
2 Canterbury 139 3
3 Capital and Coast 88 0
4 Counties Manukau 103 2
Treat the special character
df.DHB = list(i.replace('ā','a') for i in df.DHB)
df.tail()
DHB Number of cases Change in last 24 hours
16 Wairarapa 8 0
17 Waitemata 200 5
18 West Coast 5 0
19 Whanganui 7 0
20 Total 1,366 17

Now we get the table of addresses and the cases No. data for mapping.

Then we need to get the location data so the program know where to draw.

Geolocation data

read out the center of each DHB cities
df3 = pd.read_csv('DHBLocation.csv')
df3
DHB Y X
0 Northland 173.825907 -35.489931
1 Waitemata 174.546651 -36.563964
2 Auckland 175.156221 -36.517984
3 Counties Manukau 174.932391 -37.187695
4 Waikato 175.356931 -38.048669
5 Lakes 176.123138 -38.653552
6 Bay of Plenty 176.918989 -38.091072
7 Tairawhiti 177.921101 -38.281284
8 Taranaki 174.467469 -39.315027
9 Hawke's Bay 176.796960 -39.412258
10 Whanganui 175.519157 -39.609703
11 MidCentral 175.810108 -40.382262
12 Hutt Valley 175.051906 -41.160282
13 Capital and Coast 174.897246 -41.092649
14 Wairarapa 175.628010 -41.099410
15 Nelson Marlborough 173.137270 -41.362035
16 West Coast 170.870664 -42.794808
17 Canterbury 172.366210 -43.075242
18 South Canterbury 170.656863 -44.146524
19 Southern 168.789955 -45.442032
Merge the table of case No, and location based on DHB cities
df4 = pd.merge(df3, df, how='left', on='DHB')
df4.head()
DHB Y X Number of cases Change in last 24 hours
0 Northland 173.825907 -35.489931 26 1
1 Waitemata 174.546651 -36.563964 200 5
2 Auckland 175.156221 -36.517984 180 4
3 Counties Manukau 174.932391 -37.187695 103 2
4 Waikato 175.356931 -38.048669 177 0
df4['Number of cases'] = df4['Number of cases'].astype(int) # change the values to int

Mapping

create a list of linear spacing for color range
nzta_geo = 'DHB.geojson' #this file is taken from the LINZ website dated on 2016, it including the polygon information of each DHB cities

# create a numpy array of length 6 and has linear spacing from the minium cases No. to the maximum cases No.
import math
threshold_scale = np.linspace(df4['Number of cases'].min(),
                              df4['Number of cases'].max(),
                              6, dtype=int)
threshold_scale = threshold_scale.tolist() # change the numpy array to a list


threshold_scale[-1] = threshold_scale[-1] + 1 # make sure that the last value of the list is greater than the maximum cases No.
threshold_scale
[3, 44, 85, 127, 168, 211]
Choropleth mapping

#Choropleth mapping
#creat the map object
world_map = folium.Map(location=[-39.58,175.3698], zoom_start=5.5, tiles='Stamen Terrain')
folium.Choropleth(
    geo_data = nzta_geo,
    data=df4, #data source
    columns=['DHB', 'Number of cases'],  # data columns
    key_on='feature.properties.DHB2015_Na', # the geometry infomation on the geojson data
    threshold_scale=threshold_scale,
    fill_color='YlOrRd', #color
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name='Confirmed Coronavirus Cases in NZ(Click icon check more details)',
#     reset=True
).add_to(world_map)

folium.LayerControl().add_to(world_map)

<folium.map.LayerControl at 0x1cebe5c6438>
Add the case No. icon on the map
#icon mapping
for i in range(len(df4.DHB)):

    folium.Marker(
        location=df4.iloc[i,[2,1]],
        popup=(r'{0};\nTTL: {1};\n 24H: {2}'.format(df4.iloc[i,0],df4.iloc[i,3],df4.iloc[i,4])),
        icon=folium.Icon(color='green')
    ).add_to(world_map)
Plotting the map out
# display map
world_map
Save the map to local disk as a website, and we can share with friend or post online.
import datetime
today_date=str(datetime.date.today())
world_map.save('Covid-19 Cases in New Zealand-map{}.html'.format(today_date))

final map result:https://fordy7014.github.io/YangWeb/

Reference

  • https://www.stats.govt.nz/
  • https://www.health.govt.nz/our-work/diseases-and-conditions/covid-19-novel-coronavirus/covid-19-current-situation/covid-19-current-cases

  • Author: Ford Yang
    Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Ford Yang !
      TOC