Search code examples
geopandasfolium

Plotting Linestrings with a Colomap - Geopandas and Folium


I have a geopandas data frame containing ~500 linestring and a column named total containing a number between 0 and 1.

I want to plot the linestrings on a folium map with a color that depends on the value of total. Thus, I defined a colormap as follows:

colormap = cm.LinearColormap(colors=['lightblue','blue'])

and I am plotting everything with the following code:

m = folium.Map(zoom_start=10, tiles='CartoDB positron')

for _, r in gdf.iterrows():
    geo_j = gpd.GeoSeries(r['geometry']).to_json()
    geo_j = folium.GeoJson(data=geo_j,
                           style_function=lambda x:
                                      {'lineColor':colormap(r['total']),
                                       'color': colormap(r['total']),
                                       'fill':True,
                                       'opacity': 1, 
                                       'fillColor': colormap(r['total'])})
    geo_j.add_to(m)

I tried with all the combinations of linecolor, color, fillcolor, opacity and whatsoever but all the lines are always plotted with the same color even if colormap(r['total'] works correctly (always different rgb are retrieved):

enter image description here

can anyone help?


Solution

  • import requests
    import geopandas as gpd
    import plotly.graph_objects as go
    import itertools
    import numpy as np
    import pandas as pd
    import shapely.geometry
    
    # get geometry of london underground stations
    gdf = gpd.GeoDataFrame.from_features(
        requests.get(
            "https://raw.githubusercontent.com/oobrien/vis/master/tube/data/tfl_stations.json"
        ).json()
    )
    
    # limit to zone 1 and stations that have larger number of lines going through them
    gdf = (
        gdf.loc[gdf["zone"].isin(["1", "2"]) & gdf["lines"].apply(len).gt(2)]
        .reset_index(drop=True)
        .rename(columns={"id": "tfl_id", "name": "id"})
    )
    
    # wanna join all valid combinations of stations...
    combis = np.array(list(itertools.combinations(gdf.index, 2)))
    
    # generate dataframe of all combinations of stations
    gdf_c = (
        gdf.loc[combis[:, 0], ["geometry", "id"]]
        .assign(right=combis[:, 1])
        .merge(
            gdf.loc[:, ["geometry", "id"]],
            left_on="right",
            right_index=True,
            suffixes=("_start_station", "_end_station"),
        )
    )
    
    # generate linestrings between stations
    gdf = gpd.GeoDataFrame(
        geometry=gdf_c.select_dtypes("geometry").apply(shapely.geometry.LineString, axis=1),
        data=gdf_c,
        crs="EPSG:4326",
    )
    gdf["total"] = np.random.uniform(0, 1, len(gdf))
    
    # now use explore that uses folium
    gdf.explore("total", cmap="Blues", tiles="CartoDB positron")
    

    enter image description here