Search code examples
pythongeojsonfoliumchoroplethzipcode

Python / Folium / Choropleth: TypeError: ufunc 'isnan' not supported


I'm trying to plot a choropleth map on zipcodes in LA in order to show / highlight values of a certain column of the dataframe. So far, I'm receiving following error message with my code:

'TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe'' '

After days of research on google, stack, studying the documentaries, reviewing youtube tutorials, I'm still not able to fix it. Reaching out here is the last resort.

Please see the code below, as well as the Traceback:

!pip install geopandas
!pip install geopy
!pip install folium


import pandas as pd
import folium
import 


from functools import reduce
from io import BytesIO
import requests
import os
import geopandas as gpd


LA_map = folium.Map(location= [34.052235, -118.243683], zoom_start= 10)

df_geojson = gpd.read_file(
r'https://raw.githubusercontent.com/tzick90/datasources/main/map.geojson'
)
LA_zipcodes = df_geojson['zipcode'].tolist()

CA_househould_income = '1Gfa2sG0SzDdgV9bztVZvZh8U9ti0ei_BpZr3swGY3mg'
CA_househould_income_file = f'https://docs.google.com/spreadsheets/d/{CA_househould_income}/export?format=csv'
r2 = requests.get(CA_househould_income_file)
CA_HI = pd.read_csv(BytesIO(r2.content))


LA_avg_income = CA_HI['zip_code'].isin(LA_zipcodes)
LA_avg_income_clean = CA_HI[LA_avg_income].reset_index()
LA_avg_income_clean.rename(columns = {'zip_code':'zipcode'}, inplace= True)
LA_avg_income_clean['zipcode'] = LA_avg_income_clean['zipcode'].astype('str')

LA_avg_income_clean_list = LA_avg_income_clean['zipcode'].tolist()
LA_zipcode_clean = df_geojson['zipcode'].isin(LA_avg_income_clean_list)
LA_zipcode_clean_final = df_geojson[LA_zipcode_clean].reset_index()


LA_zipcode_clean_final['zipcode_'] = LA_zipcode_clean_final['zipcode']
LA_avg_income_clean['zipcode_'] = LA_avg_income_clean['zipcode']
LA_avg_income_clean['zipcode'] = LA_avg_income_clean['zipcode'].astype('str')

LA_zipcode_clean_final1 = LA_zipcode_clean_final.sort_values(by= 'zipcode', ascending = True).set_index('zipcode_')
LA_avg_income_clean1 = LA_avg_income_clean.sort_values(by= 'zipcode', ascending = True).set_index('zipcode_')




zip_boundries1 = LA_zipcode_clean_final1.to_json()

folium.Choropleth(
    geo_data= zip_boundries1,
    name= 'choropleth',
    data= LA_avg_income_clean1,
    columns= ['zipcode','Avg. Income/H/hold'],
    key_on= 'feature.properties.zipcode',
    fill_color= 'YlGn',
    #nan_fill_opacity= 0.1,
    fill_opacity=0.3,
    line_opacity=0.9,
    legend_name= "Average Income per Household in USD",
).add_to(LA_map)

display(LA_map)

The following is the error message I nearly constantly recieve:

TypeError                                 Traceback (most recent call last)
<ipython-input-185-62a5660e5e7c> in <module>
----> 1 folium.Choropleth(
      2     geo_data= zip_boundries1,
      3     name= 'choropleth',
      4     data= LA_avg_income_clean1,
      5     columns= ['zipcode','Avg. Income/H/hold'],

~/opt/anaconda3/lib/python3.8/site-packages/folium/features.py in __init__(self, geo_data, data, columns, key_on, bins, fill_color, nan_fill_color, fill_opacity, nan_fill_opacity, line_color, line_weight, line_opacity, name, legend_name, overlay, control, show, topojson, smooth_factor, highlight, **kwargs)
   1211         if color_data is not None and key_on is not None:
   1212             real_values = np.array(list(color_data.values()))
-> 1213             real_values = real_values[~np.isnan(real_values)]
   1214             _, bin_edges = np.histogram(real_values, bins=bins)
   1215 

TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

Any suggestions how to fix / resolve the error? Every recomendations or solutions are much appreciated.

Best Regards


Solution

  • We have simplified your assignment and created a code. The challenge was that the zip code must be a string in each data, otherwise folium will not support it. Also, the values represented in the zip code area are strings in dollar notation, so they need to be converted to numbers.

    import pandas as pd
    import folium
    from io import BytesIO
    import requests
    import geopandas as gpd
    from re import sub
    from decimal import Decimal
    
    df_geojson = gpd.read_file(r'https://raw.githubusercontent.com/tzick90/datasources/main/map.geojson')
    LA_zipcodes = df_geojson['zipcode'].tolist()
    df_geojson['zipcode'] = df_geojson['zipcode'].astype(str)
    
    CA_househould_income = '1Gfa2sG0SzDdgV9bztVZvZh8U9ti0ei_BpZr3swGY3mg'
    CA_househould_income_file = f'https://docs.google.com/spreadsheets/d/{CA_househould_income}/export?format=csv'
    r2 = requests.get(CA_househould_income_file)
    CA_HI = pd.read_csv(BytesIO(r2.content))
    CA_HI.rename(columns = {'zip_code':'zipcode'}, inplace= True)
    CA_HI['zipcode'] = CA_HI['zipcode'].astype(str)
    CA_HI['Avg. Income/H/hold'] = CA_HI['Avg. Income/H/hold'].apply(lambda x: Decimal(sub(r'[^\d.]', '', x)))
    CA_HI['Avg. Income/H/hold'] = CA_HI['Avg. Income/H/hold'].astype(int)
    
    LA_map = folium.Map(location= [34.052235, -118.243683], zoom_start= 10)
    
    folium.Choropleth(
        geo_data= df_geojson.to_json(),
        name= 'choropleth',
        data= CA_HI,
        columns= ['zipcode','Avg. Income/H/hold'],
        key_on= 'feature.properties.zipcode',
        fill_color= 'YlGn',
        #nan_fill_opacity= 0.1,
        fill_opacity=0.3,
        line_opacity=0.9,
        legend_name= "Average Income per Household in USD",
    ).add_to(LA_map)
    
    display(LA_map)
    

    enter image description here