pandasdataframeleafletfolium

Loop through pandas dataframe to create separate Folium maps


I have a pandas dataframe that looks like this:

import pandas as pd
d = {'user': ['Peter', 'Peter', 'Peter', 'Peter', 'David', 'David', 'David', 'Emma', 'Joyce', 'Joyce', 'Joyce'], 'date': ['2019-03-04', '2019-03-04', '2019-03-04', '2019-03-04', '2019-03-04', '2019-03-04', '2019-03-04', '2019-03-04', '2019-03-04', '2019-03-04', '2019-03-04'], 'lat': [37.749798119650926, 37.751028173710736, 37.751698332490214, 37.75180012822952, 38.122893081890844, 38.124108467926035, 38.12743379574882, 37.89363489791644, 37.53620628385582, 37.53804390907164, 37.54044296272588], 'lon': [-122.49230146408082, -122.49229073524474, -122.49170064926147, -122.48974800109862, -122.24205136299133, -122.23907947540283, -122.23867177963257, -122.07653760910033, -121.99707984924316, -121.99315309524536, -121.9914150238037]}
df = pd.DataFrame(data=d)
df

user    date        lat         lon
Peter   2019-03-04  37.749798   -122.492301
Peter   2019-03-04  37.751028   -122.492291
Peter   2019-03-04  37.751698   -122.491701
Peter   2019-03-04  37.751800   -122.489748
David   2019-03-04  38.122893   -122.242051
David   2019-03-04  38.124108   -122.239079
David   2019-03-04  38.127434   -122.238672
Emma    2019-03-04  37.893635   -122.076538
Joyce   2019-03-04  37.536206   -121.997080
Joyce   2019-03-04  37.538044   -121.993153
Joyce   2019-03-04  37.540443   -121.991415

I would like to create four separate folium maps grouped per user that shows the latitude longitude coordinates as points on the map and the lines between these points. In the end I want to end up with four maps named after the user: Peter.html, David.html, Emma.html and Joyce.html.

So far I've come up with the following, however this only generates the file Peter.html with all coordinates plotted. Any ideas what I'm missing?

import folium
# Create map
m = folium.Map(location=[37.733795, -122.446747], 
               zoom_start=9, 
               min_zoom=10, 
               max_zoom=19,
               control_scale=True)

# Add location markers for GPS points to holding object
for user, data in df.groupby('user'):
    for row in df.itertuples():
        folium.CircleMarker(
            location=[row.lat, row.lon],
            radius=4,
            fill=True,
            fill_opacity=0.5
        ).add_to(m)
# Add blue polyline between raw GPS measurements
    folium.PolyLine(
        locations=df[['lat','lon']].values,
        opacity=0.8,
        weight=3
    ).add_to(m)
    m.save(df['user'].iloc[0]+".html")

Solution

  • Filter your main dataframe by user and create map from filtered dataframe.

    import pandas as pd
    import folium
    
    d = {}
    df = pd.DataFrame(data=d)
    users = list(df.user.unique())
    
    def create_user_map(user):
        m = folium.Map(location=[37.733795, -122.446747], 
               zoom_start=9, 
               min_zoom=10, 
               max_zoom=19,
               control_scale=True)
     
        df_user = df[df.user==user]
        for row in df_user.itertuples():
             folium.CircleMarker( location=[row.lat, row.lon],
                radius=4,
                fill=True,
               fill_opacity=0.5).add_to(m)
             # Add blue polyline between raw GPS measurements
             folium.PolyLine(
                locations=df_user[['lat','lon']].values,
                opacity=0.8,
                weight=3).add_to(m)
         return m
    
    for user in users:
        user_map = create_user_map(user)
        user_file = f"{user}.html"
        user_map.save(user_file)