1 minute read

The theme of the third day is Polygons:

A map with polygons. Regions, countries, lakes—this day is for defined shapes that fill space.

Data

For today, I downloaded two datasets provided at the Dresden OpenDataPortal to visualize the number of citizens living in each of Dresden’s 64 districts:

Implementation

Today, we create an interactive map again. Therefore, the imports look similar to the ones from day one. However, this day, we also need some functionality to create a colormap.

The read_dresden_csv function has been introduced yesterday.

1
2
3
4
5
6
7
8
from pathlib import Path

import branca.colormap as cm
import folium
import geopandas as gpd
import pandas as pd

from utils import read_dresden_csv

Now, we can load today’s data sets:

1
2
gdf_districts = read_dresden_csv("data/dresden/stadtteile.csv", geometry_column="shape")
df_citizens = pd.read_csv("data/dresden/bevoelkerung.csv", delimiter=",", header=0)

The citizens data set contains information about the number of habitants per district, differentiated along two dimensions: gender (male / female) and marital status (single, married, divorced, widowed). Since we are interested in overall numbers only, we group records by district (“blocknr”) and sum the column that holds the number of citizens (“Anzahl Einwohner”). Furthermore, the district’s ID (“blocknr”) is extracted from a column that contains a string that is comprised of the ID and name.

This ID is then used to assign the number of citizens to the right district.

1
2
3
4
5
6
7
8
9
10
11
citizens = (
    df_citizens.assign(
        blocknr=df_citizens["Stadtteil zus."].str.split(" ").str[0].astype(int)
    )
    .groupby("blocknr")
    .sum()["Anzahl Einwohner"]
)

gdf_districts = gdf_districts.set_index("blocknr").assign(
    citizens=citizens,
).fillna(0)

Now that the data is consolidated, we can create a map that visualizes all the districts of Dresden using color-coded polygons. The geometry information is retrieved from the WKT strings for each district (cf. day one). For encoding the number of citizens, we set up a colormap that goes from white (0 inhabitants) up to red (maximum number of inhabitants per district).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
map = folium.Map(tiles="CartoDB positron")
cmap = cm.LinearColormap(["white", "orange", "red"], vmin=0, vmax=citizens.max())

folium.GeoJson(
    gdf_districts,
    popup=folium.GeoJsonPopup(["bez", "citizens"]),
    tooltip=folium.GeoJsonTooltip(["bez", "citizens"]),
    style_function=lambda feature: {
        "fillColor": cmap(feature["properties"]["citizens"]),
        "fillOpacity": .9,
        "color": "black",
        "weight": 1,
        # "dashArray": "5, 5",
    },

).add_to(map)

map.fit_bounds(map.get_bounds())
map
Make this Notebook Trusted to load map: File -> Trust Notebook