Search code examples
pythonpython-3.xdata-visualizationvisualizationfolium

Dataformat for Folium HeatMapWithTime


The end state that I'm trying to achieve is to create a heat map in folium that has a slider to adjust the heatmap based on years.

I've been following this tutorial here and making adjustments, but when I print the map, nothing shows.

This is the code I'm trying to use:

def generatebasemap(default_location=[47.670,-122.394], default_zoom_start=7):
    basemap = folium.Map(location=default_location, zoom_start=default_zoom_start)
    return basemap

basemap=generatebasemap()
yr = pd.DataFrame()
yr['yr'] = gdf['yr_built']#.unique()
yr1 = yr.values.tolist()
listing_summary_history = []
for i in yr1:
    listing_summary_history.append(i[0])
print(listing_summary_history)
from folium import plugins
from folium.plugins import HeatMap 

crs = {'init': 'epsg:4326'}

date_index = listing_summary_history[::-1]

locs_history_map = folium.Map(location=[47.67,-122.39],
                              zoom_start = 13, tiles='cartodbpositron')

hm = plugins.HeatMapWithTime(
    data=gdf['pl'],
    index=date_index,
    auto_play=True,
    radius=4,
    max_opacity=0.3
)
hm.add_to(locs_history_map)

This is the output

My Data below: Price --> What I want the heatmap to display, yr_built --> What I want the slider to alter in the heat map.

    price   lat     lon     yr_built    geometry    pl
0   530000.0    47.6700     -122.394    1900    POINT (-122.39400 47.67000)     13.180632
1   740500.0    47.6981     -122.368    1900    POINT (-122.36800 47.69810)     13.515081
2   625000.0    47.5872     -122.390    1900    POINT (-122.39000 47.58720)     13.345507
3   595000.0    47.6582     -122.345    1900    POINT (-122.34500 47.65820)     13.296317
4   485000.0    47.6385     -122.370    1900    POINT (-122.37000 47.63850)     13.091904
5   565000.0    47.6653     -122.372    1900    POINT (-122.37200 47.66530)     13.244581
6   352950.0    47.6598     -122.348    1900    POINT (-122.34800 47.65980)     12.774082
7   440000.0    47.5473     -122.396    1900    POINT (-122.39600 47.54730)     12.994530
8   712000.0    47.6510     -122.341    1900    POINT (-122.34100 47.65100)     13.475833
9   490000.0    47.6726     -122.381    1900    POINT (-122.38100 47.67260)     13.102161

Load the data like this:

import pandas as pd
import geopandas as gpd
from io import StringIO

data = '''ID;price;lat;lon;yr_built;geometry;pl;
0;530000.0;47.6700;-122.394;1900;POINT;(-122.39400, 47.67000);13.180632
1;740500.0;47.6981;-122.368;1900;POINT;(-122.36800, 47.69810);13.515081
2;625000.0;47.5872;-122.390;1900;POINT;(-122.39000, 47.58720);13.345507
3;595000.0;47.6582;-122.345;1900;POINT;(-122.34500, 47.65820);13.296317
4;485000.0;47.6385;-122.370;1900;POINT;(-122.37000, 47.63850);13.091904
5;565000.0;47.6653;-122.372;1900;POINT;(-122.37200, 47.66530);13.244581
6;352950.0;47.6598;-122.348;1900;POINT;(-122.34800, 47.65980);12.774082
7;440000.0;47.5473;-122.396;1900;POINT;(-122.39600, 47.54730);12.994530
8;712000.0;47.6510;-122.341;1900;POINT;(-122.34100, 47.65100);13.475833
9;490000.0;47.6726;-122.381;1900;POINT;(-122.38100, 47.67260);13.102161'''

df = pd.read_csv(StringIO(data), sep = ";")
df = df.set_index('ID')

gdf = gpd.GeoDataFrame(
    df, geometry = gpd.points_from_xy(df.lon, df.lat))
gdf

Solution

  • The problem is the format of data=gdf['pl'] which needs to be:

    OrderedDict([(year, [[lat, lon], [lat, lon], ...])])

    With the help of this previous answer i was able to get it working:

    def generatebasemap(default_location=[47.670,-122.394], default_zoom_start=7):
        basemap = folium.Map(location=default_location, zoom_start=default_zoom_start)
        return basemap
    
    basemap = generatebasemap()
    
    locs_history_map = folium.Map(location=[47.67,-122.39],
                                  zoom_start = 13, tiles='cartodbpositron')
    
    data = defaultdict(list)
    for r in gdf.itertuples():
        data[r.yr_built].append([r.lat, r.lon])
        
    data = OrderedDict(sorted(data.items(), key=lambda t: t[0]))
    
    hm = plugins.HeatMapWithTime(data=list(data.values()),
                         index=list(data.keys()), 
                         radius=10,
                         auto_play=True,
                         max_opacity=0.3)
    
    
    hm.add_to(locs_history_map)
    
    locs_history_map.save("heat_map.html")
    locs_history_map
    

    Output: enter image description here