Search code examples
pythonpandasleafletgeojsonfolium

Set color for missing values in folium choropleth


I have a dataframe with some countries and variables and I would like to produce a choropleth map with folium, using a geojson file for the entire world. I have a problem with folium assigning maximum value on a color scale to countries that are not present in my dataframe. Minimum exaple below:

import random
import pandas as pd
import folium
import json

map_data = pd.DataFrame({
    'A3':['POL', 'CZE', 'SVK', 'HUN', 'AUT'],
    'value':random.sample(range(10), 5)
})

m = folium.Map(
    location = [50, 15], 
    zoom_start = 4
)

m.choropleth(
    geo_data = 'https://github.com/simonepri/geo-maps/releases/download/v0.6.0/countries-land-10km.geo.json',
    data = map_data,
    columns = ['A3', 'value'],
    key_on = 'feature.properties.A3',
    fill_color = 'YlOrRd'
)

enter image description here

My question is the following: How can I tell folium to assign a specific color (e.g., gray or transparent) to missing countries (i.e., those present in json file but not in map_data), instead of coloring them as a maximum value for given variable (which is a strange behavior)?


Solution

  • It seems there in no way to achieve that with choropleth method. I found a workaround with custom style_function and GeoJson instead of using choropleth:

    import random
    import pandas as pd
    import folium
    from branca.colormap import LinearColormap
    import json
    
    map_data = pd.DataFrame({
        'A3':['POL', 'CZE', 'SVK', 'HUN', 'AUT'],
        'value':random.sample(range(10), 5)
    })
    
    map_dict = map_data.set_index('A3')['value'].to_dict()
    
    color_scale = LinearColormap(['yellow','red'], vmin = min(map_dict.values()), vmax = max(map_dict.values()))
    
    def get_color(feature):
        value = map_dict.get(feature['properties']['A3'])
        if value is None:
            return '#8c8c8c' # MISSING -> gray
        else:
            return color_scale(value)
    
    m = folium.Map(
        location = [50, 15], 
        zoom_start = 4
    )
    
    folium.GeoJson(
        data = 'https://github.com/simonepri/geo-maps/releases/download/v0.6.0/countries-land-10km.geo.json',
        style_function = lambda feature: {
            'fillColor': get_color(feature),
            'fillOpacity': 0.7,
            'color' : 'black',
            'weight' : 1,
        }    
    ).add_to(m)
    

    enter image description here