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