0

The colors in the loop below do not change and they are constant. I do not know why is that?

Thanks in advance

location = (-32.337402, 117.871796)
m = folium.Map(location=location, zoom_start=7, control_scale=True, prefer_canvas=True)

# setting a color palettte
palette = sns.color_palette(None, len(df.name.unique())).as_hex()
palette = [i for i in palette]

for id, item in enumerate(df.name.unique()):
        color = palette[id]
        polygons_gjson = folium.features.GeoJson(df.loc[df.name == item, 'geometry'], 
                                        style_function=lambda x: {'weight': 1,
                                        'color': 'black',
                                        'fillColor': color,
                                        'fillOpacity': 1}, name = 'Paddocks delivering to {} using: '.format(str(df.site_name.values[0])) + 
                                                str(item) + ' gate', control=True)
        polygons_gjson.add_to(m)

m
MJ313
  • 75
  • 1
  • 1
  • 7

2 Answers2

1

Hi guys I found this awesome answer, that in summary states states that

"style_function is not executed immediately in the loop, but later. At that time, fillColor will be retrieved from the outer scope (because it's not defined in the inner scope created by the lambda expression), where it will have the last value at this point."

This is the link https://stackoverflow.com/a/53816162/14919380

MJ313
  • 75
  • 1
  • 1
  • 7
0
  • you are correct that it's a scoping issue in the lambda function. There is only one so it will be the last value
  • IMHO it's far better to use a property of the geojson feature to define color. Hence
df["__color"] = df["name"].map({n: c for n, c in zip(df.name.unique(), palette)})
  • then use this property in the lambda function
  • have used geopandas standard geometry to make this a MWE (compatible version of df)
import folium
import pandas as pd
import seaborn as sns
import geopandas as gpd
import numpy as np

# simulate data
df = (
    gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
    .sample(50)
    .assign(
        name=lambda d: np.random.choice(list("ABCDEF"), len(d)),
        site_name=lambda d: np.random.choice(list("GHIJKL"), len(d)),
    )
)

location = (-32.337402, 117.871796)
m = folium.Map(location=location, zoom_start=7, control_scale=True, prefer_canvas=True)

# setting a color palettte
palette = sns.color_palette(None, len(df.name.unique())).as_hex()
palette = [i for i in palette]
# assign color as column to geodataframe
df["__color"] = df["name"].map({n: c for n, c in zip(df.name.unique(), palette)})
for id, item in enumerate(df.name.unique()):
    polygons_gjson = folium.features.GeoJson(
        df.loc[df.name == item, ["geometry", "__color"]],  # color as well
        style_function=lambda x: {
            "weight": 1,
            "color": "black",
            "fillColor": x["properties"][
                "__color"
            ],  # use property of feature to avoid scoping issues
            "fillOpacity": 1,
        },
        name="Paddocks delivering to {} using: ".format(str(df.site_name.values[0]))
        + str(item)
        + " gate",
        control=True,
    )
    polygons_gjson.add_to(m)

m
Rob Raymond
  • 29,118
  • 3
  • 14
  • 30