Skip to content

API reference

map_nl.MapNL

Bases: BaseMapNL

A class for creating custom PC4 maps of the Netherlands using folium.GeoJson.

Source code in map_nl/map/map.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
class MapNL(BaseMapNL):
    """A class for creating custom PC4 maps of the Netherlands using `folium.GeoJson`."""

    def plot(self, df: pd.DataFrame, value_column_name: str, pc4_column_name: str, **kwargs) -> folium.Map:  # type: ignore
        """Creates and adds a custom map layer to the Folium map instance.

        This method processes the input DataFrame and GeoJSON data to create a
        Folium GeoJson layer, which is then added to the map.

        You can also pass any arguments to this function that are accepted by `folium.GeoJson`. For example,
        to add custom fill colors to the plot based on the column 'my_feature' in the DataFrame `df`, do the following:

        ```
        def get_color(value):
            if not value:
                return "grey"
            if value > 500:
                return "green"
            else:
                return "blue"

        def style(feature):
            return {"fillColor": get_color(feature.get("properties").get("my_feature"))}

        m = MapNL(geojson_simplify_tolerance=0.0001).plot(
            df, pc4_column_name="pc4", value_column_name="my_feature", style_function=style
        )
        ```

        Args:
            df (pd.DataFrame): DataFrame containing the data for the map.
            value_column_name (str): Name of the column in df that contains the values to be visualized.
            pc4_column_name (str): Name of the column in df that contains the PC4 area codes.
            **kwargs: Additional keyword arguments to customize the GeoJson layer.

        Returns:
            folium.Map: The Folium Map object with the custom layer added.
        """

        df = self._prepare_input_data(df, pc4_column_name)
        pc4_geojson = self._get_geojson()
        pc4_geojson = self._add_values_to_geojson(pc4_geojson, df)
        tooltip = self._get_default_tooltip(value_column_name)

        default_args = {
            "weight": 1,
            "opacity": 1,
            "color": "black",
            "dashArray": "3",
            "fillOpacity": 0.7,
            "tooltip": tooltip,
        }

        plot_args = {**default_args, **kwargs}
        folium.GeoJson(pc4_geojson, **plot_args).add_to(self.m)

        folium.LayerControl().add_to(self.m)

        return self.m

    @staticmethod
    def _prepare_input_data(df: pd.DataFrame, pc4_column_name: str) -> pd.DataFrame:
        df.rename(columns={pc4_column_name: "pc4_code"}, inplace=True)
        df["pc4_code"] = df["pc4_code"].astype("str")
        return df

    @staticmethod
    def _add_values_to_geojson(geojson: dict, df: pd.DataFrame) -> dict:
        gdf = gpd.GeoDataFrame.from_features(geojson["features"])
        merged_gdf = gdf.merge(df, on="pc4_code", how="left")
        return merged_gdf.to_json()

    @staticmethod
    def _get_default_tooltip(value_column_name: str) -> folium.GeoJsonTooltip:
        return folium.GeoJsonTooltip(
            fields=["pc4_code", "gem_name", value_column_name],
            aliases=["PC4:", "Gemeente:", f"{value_column_name}:"],
            localize=True,
            sticky=False,
            labels=True,
            style="""
                background-color: #F0EFEF;
                border: 2px solid black;
                border-radius: 3px;
                box-shadow: 3px;
            """,
            max_width=800,
        )

__init__(url='https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets/georef-netherlands-postcode-pc4/exports/geojson?lang=en&timezone=Europe%2FBerlin', data_dir='.map_nl', geojson_simplify_tolerance=None, **kwargs)

Parameters:

Name Type Description Default
url str

URL to download the GeoJSON file. Defaults to a file from https://public.opendatasoft.com.

'https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets/georef-netherlands-postcode-pc4/exports/geojson?lang=en&timezone=Europe%2FBerlin'
data_dir str

Directory to save the downloaded GeoJSON file. Defaults to .map_nl.

'.map_nl'
geojson_simplify_tolerance float | None

Tolerance level for GeoJSON simplification. If None, no simplification is performed. Lower values lead to simpler maps. Sensible values for coordinates stored in degrees are in the range of 0.0001 to 10. Defaults to None.

None
**kwargs

Additional keyword arguments to be passed to the folium.Map() function. By default, only location and zoom_start are passed with default values.

{}
Source code in map_nl/map/base.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
def __init__(  # type: ignore
    self,
    url: str = "https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets/georef-netherlands-postcode-pc4/exports/geojson?lang=en&timezone=Europe%2FBerlin",
    data_dir: str = ".map_nl",
    geojson_simplify_tolerance: float | None = None,
    **kwargs,
) -> None:
    """
    Args:
        url (str, optional): URL to download the GeoJSON file. Defaults to a file from https://public.opendatasoft.com.
        data_dir (str, optional): Directory to save the downloaded GeoJSON file. Defaults to `.map_nl`.
        geojson_simplify_tolerance (float | None, optional): Tolerance level for GeoJSON simplification.
            If None, no simplification is performed. Lower values lead to simpler maps. Sensible values for
            coordinates stored in degrees are in the range of 0.0001 to 10. Defaults to None.
        **kwargs: Additional keyword arguments to be passed to the folium.Map() function. By default, only `location`
            and `zoom_start` are passed with default values.
    """
    self.geojson_simplify_tolerance = geojson_simplify_tolerance
    self.geojson_path = Path(data_dir) / "nl-pc4-map.geojson"
    self.url = url

    Path(data_dir).mkdir(parents=True, exist_ok=True)

    map_args = {**DEFAULT_MAP_ARGS, **kwargs}
    self.m = folium.Map(**map_args)

plot(df, value_column_name, pc4_column_name, **kwargs)

Creates and adds a custom map layer to the Folium map instance.

This method processes the input DataFrame and GeoJSON data to create a Folium GeoJson layer, which is then added to the map.

You can also pass any arguments to this function that are accepted by folium.GeoJson. For example, to add custom fill colors to the plot based on the column 'my_feature' in the DataFrame df, do the following:

def get_color(value):
    if not value:
        return "grey"
    if value > 500:
        return "green"
    else:
        return "blue"

def style(feature):
    return {"fillColor": get_color(feature.get("properties").get("my_feature"))}

m = MapNL(geojson_simplify_tolerance=0.0001).plot(
    df, pc4_column_name="pc4", value_column_name="my_feature", style_function=style
)

Parameters:

Name Type Description Default
df DataFrame

DataFrame containing the data for the map.

required
value_column_name str

Name of the column in df that contains the values to be visualized.

required
pc4_column_name str

Name of the column in df that contains the PC4 area codes.

required
**kwargs

Additional keyword arguments to customize the GeoJson layer.

{}

Returns:

Type Description
Map

folium.Map: The Folium Map object with the custom layer added.

Source code in map_nl/map/map.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
def plot(self, df: pd.DataFrame, value_column_name: str, pc4_column_name: str, **kwargs) -> folium.Map:  # type: ignore
    """Creates and adds a custom map layer to the Folium map instance.

    This method processes the input DataFrame and GeoJSON data to create a
    Folium GeoJson layer, which is then added to the map.

    You can also pass any arguments to this function that are accepted by `folium.GeoJson`. For example,
    to add custom fill colors to the plot based on the column 'my_feature' in the DataFrame `df`, do the following:

    ```
    def get_color(value):
        if not value:
            return "grey"
        if value > 500:
            return "green"
        else:
            return "blue"

    def style(feature):
        return {"fillColor": get_color(feature.get("properties").get("my_feature"))}

    m = MapNL(geojson_simplify_tolerance=0.0001).plot(
        df, pc4_column_name="pc4", value_column_name="my_feature", style_function=style
    )
    ```

    Args:
        df (pd.DataFrame): DataFrame containing the data for the map.
        value_column_name (str): Name of the column in df that contains the values to be visualized.
        pc4_column_name (str): Name of the column in df that contains the PC4 area codes.
        **kwargs: Additional keyword arguments to customize the GeoJson layer.

    Returns:
        folium.Map: The Folium Map object with the custom layer added.
    """

    df = self._prepare_input_data(df, pc4_column_name)
    pc4_geojson = self._get_geojson()
    pc4_geojson = self._add_values_to_geojson(pc4_geojson, df)
    tooltip = self._get_default_tooltip(value_column_name)

    default_args = {
        "weight": 1,
        "opacity": 1,
        "color": "black",
        "dashArray": "3",
        "fillOpacity": 0.7,
        "tooltip": tooltip,
    }

    plot_args = {**default_args, **kwargs}
    folium.GeoJson(pc4_geojson, **plot_args).add_to(self.m)

    folium.LayerControl().add_to(self.m)

    return self.m

map_nl.map.choropleth.ChoroplethMapNL

Bases: BaseMapNL

A class for creating Choropleth maps of the Netherlands using folium.Choropleth.

Source code in map_nl/map/choropleth.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class ChoroplethMapNL(BaseMapNL):
    """A class for creating Choropleth maps of the Netherlands using `folium.Choropleth`."""

    def plot(  # type: ignore
        self, df: pd.DataFrame, value_column_name: str, pc4_column_name: str, tooltip: bool = True, **kwargs
    ) -> folium.Map:
        """This method takes a pandas DataFrame with PC4-data and plots a Choropleth map based on these data.
        Any **kwargs are passed on to `folium.Choropleth`. For example, to change the fill color, run

        ```
        m = ChoroplethMapNL(...).plot(..., fill_opacity=1)
        ```

        Args:
            df (pd.DataFrame): DataFrame containing the data for the Choropleth map.
            value_column_name (str): Name of the column in df that contains the values to be visualized.
            pc4_column_name (str): Name of the column in df that contains the postal code (PC4) information.
            tooltip (bool): Add a simple tooltip.
            **kwargs: Additional arguments that are passed to `folium.Choropleth`.

        Returns:
            folium.Map: The Folium Map object with the Choropleth layer added.
        """

        pc4_geojson = self._get_geojson()

        default_args = {
            "geo_data": pc4_geojson,
            "name": "choropleth",
            "data": df,
            "columns": [pc4_column_name, value_column_name],
            "key_on": "feature.properties.pc4_code",
            "fill_color": "Blues",
            "fill_opacity": 0.8,
            "line_opacity": 0.2,
            "nan_fill_color": "white",
        }
        choropleth_args = {**default_args, **kwargs}

        choropleth = folium.Choropleth(**choropleth_args).add_to(self.m)

        if tooltip:
            self._add_tooltip(choropleth, df, pc4_column_name, value_column_name)

        folium.LayerControl().add_to(self.m)

        return self.m

    @staticmethod
    def _get_default_tooltip(value_column_name: str) -> folium.GeoJsonTooltip:
        return folium.GeoJsonTooltip(
            fields=["pc4_code", "gem_name", value_column_name],
            aliases=["PC4:", "Gemeente:", f"{value_column_name}:"],
            localize=True,
            sticky=False,
            labels=True,
            style="""
                background-color: #F0EFEF;
                border: 2px solid black;
                border-radius: 3px;
                box-shadow: 3px;
            """,
            max_width=800,
        )

    def _add_tooltip(
        self, choropleth: folium.Choropleth, df: pd.DataFrame, pc4_column_name: str, value_column_name: str
    ) -> None:
        df_indexed = df.set_index(pc4_column_name)
        for s in choropleth.geojson.data["features"]:
            pc4_code = int(s.get("properties")["pc4_code"])
            if pc4_code in df_indexed.index:
                s["properties"][value_column_name] = str(df_indexed.loc[pc4_code, value_column_name])
            else:
                s["properties"][value_column_name] = None
        tooltip = self._get_default_tooltip(value_column_name)
        tooltip.add_to(choropleth.geojson)

__init__(url='https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets/georef-netherlands-postcode-pc4/exports/geojson?lang=en&timezone=Europe%2FBerlin', data_dir='.map_nl', geojson_simplify_tolerance=None, **kwargs)

Parameters:

Name Type Description Default
url str

URL to download the GeoJSON file. Defaults to a file from https://public.opendatasoft.com.

'https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets/georef-netherlands-postcode-pc4/exports/geojson?lang=en&timezone=Europe%2FBerlin'
data_dir str

Directory to save the downloaded GeoJSON file. Defaults to .map_nl.

'.map_nl'
geojson_simplify_tolerance float | None

Tolerance level for GeoJSON simplification. If None, no simplification is performed. Lower values lead to simpler maps. Sensible values for coordinates stored in degrees are in the range of 0.0001 to 10. Defaults to None.

None
**kwargs

Additional keyword arguments to be passed to the folium.Map() function. By default, only location and zoom_start are passed with default values.

{}
Source code in map_nl/map/base.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
def __init__(  # type: ignore
    self,
    url: str = "https://public.opendatasoft.com/api/explore/v2.1/catalog/datasets/georef-netherlands-postcode-pc4/exports/geojson?lang=en&timezone=Europe%2FBerlin",
    data_dir: str = ".map_nl",
    geojson_simplify_tolerance: float | None = None,
    **kwargs,
) -> None:
    """
    Args:
        url (str, optional): URL to download the GeoJSON file. Defaults to a file from https://public.opendatasoft.com.
        data_dir (str, optional): Directory to save the downloaded GeoJSON file. Defaults to `.map_nl`.
        geojson_simplify_tolerance (float | None, optional): Tolerance level for GeoJSON simplification.
            If None, no simplification is performed. Lower values lead to simpler maps. Sensible values for
            coordinates stored in degrees are in the range of 0.0001 to 10. Defaults to None.
        **kwargs: Additional keyword arguments to be passed to the folium.Map() function. By default, only `location`
            and `zoom_start` are passed with default values.
    """
    self.geojson_simplify_tolerance = geojson_simplify_tolerance
    self.geojson_path = Path(data_dir) / "nl-pc4-map.geojson"
    self.url = url

    Path(data_dir).mkdir(parents=True, exist_ok=True)

    map_args = {**DEFAULT_MAP_ARGS, **kwargs}
    self.m = folium.Map(**map_args)

plot(df, value_column_name, pc4_column_name, tooltip=True, **kwargs)

This method takes a pandas DataFrame with PC4-data and plots a Choropleth map based on these data. Any **kwargs are passed on to folium.Choropleth. For example, to change the fill color, run

m = ChoroplethMapNL(...).plot(..., fill_opacity=1)

Parameters:

Name Type Description Default
df DataFrame

DataFrame containing the data for the Choropleth map.

required
value_column_name str

Name of the column in df that contains the values to be visualized.

required
pc4_column_name str

Name of the column in df that contains the postal code (PC4) information.

required
tooltip bool

Add a simple tooltip.

True
**kwargs

Additional arguments that are passed to folium.Choropleth.

{}

Returns:

Type Description
Map

folium.Map: The Folium Map object with the Choropleth layer added.

Source code in map_nl/map/choropleth.py
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def plot(  # type: ignore
    self, df: pd.DataFrame, value_column_name: str, pc4_column_name: str, tooltip: bool = True, **kwargs
) -> folium.Map:
    """This method takes a pandas DataFrame with PC4-data and plots a Choropleth map based on these data.
    Any **kwargs are passed on to `folium.Choropleth`. For example, to change the fill color, run

    ```
    m = ChoroplethMapNL(...).plot(..., fill_opacity=1)
    ```

    Args:
        df (pd.DataFrame): DataFrame containing the data for the Choropleth map.
        value_column_name (str): Name of the column in df that contains the values to be visualized.
        pc4_column_name (str): Name of the column in df that contains the postal code (PC4) information.
        tooltip (bool): Add a simple tooltip.
        **kwargs: Additional arguments that are passed to `folium.Choropleth`.

    Returns:
        folium.Map: The Folium Map object with the Choropleth layer added.
    """

    pc4_geojson = self._get_geojson()

    default_args = {
        "geo_data": pc4_geojson,
        "name": "choropleth",
        "data": df,
        "columns": [pc4_column_name, value_column_name],
        "key_on": "feature.properties.pc4_code",
        "fill_color": "Blues",
        "fill_opacity": 0.8,
        "line_opacity": 0.2,
        "nan_fill_color": "white",
    }
    choropleth_args = {**default_args, **kwargs}

    choropleth = folium.Choropleth(**choropleth_args).add_to(self.m)

    if tooltip:
        self._add_tooltip(choropleth, df, pc4_column_name, value_column_name)

    folium.LayerControl().add_to(self.m)

    return self.m