Python - Folium Choropleth Map - colors incorrect

12,719

I got it all figured out. Missing values are coloured grey, and the legend is customized with intervals of my choice. Cleaning up the geojson, removing trailing white space, and making all suburb names UPPERCASE solved a lot of problems.

Files are here

Demo image

Create Dictionary

import pandas as pd
import csv 

csv_path='Data_tables_Criminal_Incidents_Visualisation_year_ending_June_2018.csv'
df=pd.read_csv(csv_path)

# sum the number of incidents recorded for each suburb
df=df.groupby(['Suburb/Town Name'])['Incidents Recorded'].agg(
    # make the numbers numeric otherwise it just concatenates strings
    lambda x: pd.to_numeric(x, errors='coerce').sum()
)

# create a dictionary, where keys are Suburb/Town Name and values are number of incidents
suburb_dict = df.to_dict()

Style Function

def style_function(feature):
    suburb = suburb_dict.get(feature['properties']['Suburb_Name'])
    return {
        'fillColor': '#gray' if suburb is None else colormap(suburb),
        'fillOpacity': 0.6,
        #borders
        'weight': 0.2,
    }

Folium Map

import folium

world_map = folium.Map(
        location=[-38.292102, 144.727880],
        zoom_start=6,
        tiles='openstreetmap'
        )

folium.GeoJson(
    data = 'vic_for_crime_2018.geojson',
    style_function = style_function    
).add_to(world_map)

Colormap

import branca

colormap = branca.colormap.linear.YlOrRd_09.scale(0, 8500)
colormap = colormap.to_step(index=[0, 1000, 3000, 5000, 8500])
colormap.caption = 'Incidents of Crime in Victoria (year ending June 2018)'
colormap.add_to(world_map)

world_map.save('vic_final.html')
Share:
12,719
Harley
Author by

Harley

Updated on June 17, 2022

Comments

  • Harley
    Harley almost 2 years

    My problem is that suburbs are not displaying the correct color on the Folium map. For example, Dandenong and Frankston should be shaded with the darkest color as they have the highest count in the dataframe, but they are shaded with a lighter color.

    The dataframe is missing some suburbs. Those suburbs are being colored with the darkest color.

    Another problem is the csv has all suburbs in UPPERCASE but the geojson has a mixture of cases such as "Frankston", "St Kilda", or "McKinnon". It would be helpful if the choropleth code didn't care about case. I can change the text in the dataframe to make "FRANKSTON", "Frankston", and "ST KILDA", "St Kilda", but "MCKINNON" to "McKinnon" is proving a bit trickier.

    Create Dataframe

    import csv 
    import pandas as pd
    csv_path='Data_tables_Criminal_Incidents_Visualisation_year_ending_June_2018.csv'
    df=pd.read_csv(csv_path)
    
    with open(csv_path, 'r') as csvfile: 
        # creating a csv reader object 
        csvreader = csv.reader(csvfile) 
        # create a list of headings from the first row of the csv file
        headings = next(csvreader)
    
    # create a dictionary, where keys are Suburb/Town Name and values are number of occurences
    # index 2 of the headings list are the suburbs
    neighborhood_dict = df[headings[2]].value_counts().to_dict()
    
    # make first letter uppercase eg St Kilda
    neighborhood_dict = dict((k.title(), v) for k, v in neighborhood_dict.items())
    
    
    # make neighborhood_list from neighborhood_dict
    neighborhood_list=[]
    for key, value in neighborhood_dict.items():
        temp = [key,value]
        neighborhood_list.append(temp)
    
    # make dataframe from neighborhood_list
    df = pd.DataFrame(neighborhood_list, columns=['Suburb','Count'])
    
    print(df.to_string()) 
    

    Create Map

    import folium
    
    world_map = folium.Map(
            location=[-38.292102, 144.727880],
            zoom_start=6,
            tiles='openstreetmap'
            )
    
    world_map.choropleth(
            geo_data='vic.geojson',
            data=df,
            columns=['Suburb','Count'],
            key_on='feature.properties.Suburb_Name',
            fill_color='YlOrRd',
            fill_opacity=0.7,
            line_opacity=0.2,
            legend_name='Crime Rate in Victoria'
            )
    
    world_map.save('index.html')
    

    Dataframe Image

    Legend

    Map Image

  • al76
    al76 almost 3 years
    As a Frankston rate payer, thankyou for putting Frankston on the map :)