Search code examples
pythondata-visualizationfoliumchoropleth

Folium Choropleth Map - Is there a way to add crosshatching for NaN values?


Is there a way to specify cross-hatching (crossing lines) as an nan_fill_color? I am creating a few grey-scale visualizations, and currently using White or Black as the fill color does not quite convey the meaning I want.

Here is my code:

state_geo = 'us-states.json'
state_unemployment = 'myData.csv'
state_data = pd.read_csv(state_unemployment)

m = folium.Map(location=[39, -98], zoom_start=4)

folium.Choropleth(
    geo_data=state_geo,
    name='choropleth',
    data=state_data,
    columns=['State', 'unemployment'],
    key_on='feature.id',
    fill_color='Greys',
    fill_opacity=1,
    line_opacity=.1,
    line_weight = 2,
    nan_fill_color='Black',
    legend_name='Year'
).add_to(m)

folium.LayerControl().add_to(m)

m

Link to the us-states.json data:

https://raw.githubusercontent.com/python-visualization/folium/master/examples/data/us-states.json


Solution

  • NOTE: This solution utilizes geopandas. Probably a better way and hopefully someone will post it.

    import pandas as pd
    import geopandas as gpd
    import numpy as np
    import folium
    from folium.plugins import StripePattern
    
    # mock user data
    state_data = pd.DataFrame([['NE', .5],
                                ['IA', .23],
                                ['MO', np.nan],
                                ['KS', np.nan]],
                              columns=['State', 'unemployment'])
    
    
    state_geo = 'us-states.json'
    
    m = folium.Map(location=[39, -98], zoom_start=4)
    
    folium.Choropleth(
        geo_data=state_geo,
        name='choropleth',
        data=state_data,
        columns=['State', 'unemployment'],
        key_on='feature.id',
        fill_color='Greys',
        fill_opacity=1,
        line_opacity=.1,
        line_weight = 2,
        nan_fill_color='White',
        legend_name='Year'
    ).add_to(m)
    
    # geojson to geopandas dataframe
    gdf = gpd.read_file(state_geo)
    
    # creating a list of NaNs in state_data which we will user to filter our geodataframe
    nans = state_data[state_data['unemployment'].isnull()]['State'].values
    gdf_nans = gdf[gdf['id'].isin(nans)]
    
    # Not exactly a crosshatch, but its close.  Maybe you can find a better pattern
    sp = StripePattern(angle=45, color='grey', space_color='white')
    sp.add_to(m)
    
    # adding the nan layer with `sp` as the fillPattern
    folium.GeoJson(data=gdf_nans, style_function=lambda x :{'fillPattern': sp}).add_to(m)
    
    folium.LayerControl().add_to(m)
    m
    

    enter image description here