Streamlit-Folium多类牲畜地图颜色显示单一问题求助
解决Folium地图中多类牲畜差异化颜色显示问题
开发基于Streamlit和Folium的地图可视化应用,目标为鸡、猪、牛等不同类别的牲畜区域设置差异化颜色,但当前应用中所有区域仅显示单一颜色。以下是当前使用的代码:
def display_map(df, selected_states, selected_livestocks): if selected_states: df = df[df['SIG_KOR_NM'].isin(selected_states)] if 'ALL' not in selected_livestocks: df = df[df['property_type_name'].isin(selected_livestocks)] color_mapping = { 'Unknown': 'black', 'chiecken': 'green', 'pig': 'pink', 'cow': 'orange' } if not df.empty: df['geometry'] = df['geometry_coordinates'].apply( lambda x: Polygon(ast.literal_eval(x)[0]) if pd.notnull(x) else None ) map = folium.Map(location=[35.4681593,128.4765802], zoom_start=1, scrollWheelZoom=False, tiles='CartoDB positron') for _, row in df.iterrows(): if row['geometry'] is not None: if row['geometry'].is_valid: property_type_name = row['property_type_name'] color = color_mapping.get(row['property_type_name'], 'gray') folium.GeoJson(row['geometry'], style_function = lambda x: { 'color': color_mapping.get(property_type_name, 'gray'), 'fillColor': color_mapping.get(property_type_name, 'gray')}).add_to(map) folium_static(map) else : map = folium.Map(location=[ , ], zoom_start=7, scrollWheelZoom=False, tiles='CartoDB positron') return map
问题根源
问题出在style_function的lambda表达式上。循环中定义的lambda不会立即捕获当前循环的property_type_name值,而是会引用循环变量的最终值——也就是循环结束时最后一行的property_type_name,导致所有GeoJson元素都使用同一颜色。
解决方案
方案1:给lambda绑定默认参数
通过给lambda函数添加默认参数,将当前循环的property_type_name值固定下来,避免引用循环变量的最终值:
for _, row in df.iterrows(): if row['geometry'] is not None and row['geometry'].is_valid: property_type_name = row['property_type_name'] folium.GeoJson( row['geometry'], style_function=lambda x, pt=property_type_name: { 'color': color_mapping.get(pt, 'gray'), 'fillColor': color_mapping.get(pt, 'gray') } ).add_to(map)
方案2:封装独立的样式函数
将样式逻辑封装成独立函数,通过闭包传递当前的牲畜类型,代码可读性更强:
先定义样式函数:
def get_livestock_style(pt): return { 'color': color_mapping.get(pt, 'gray'), 'fillColor': color_mapping.get(pt, 'gray') }
然后在循环中调用:
for _, row in df.iterrows(): if row['geometry'] is not None and row['geometry'].is_valid: property_type_name = row['property_type_name'] folium.GeoJson( row['geometry'], style_function=lambda x: get_livestock_style(property_type_name) ).add_to(map)
修改后的完整代码(采用方案1)
import ast import pandas as pd from shapely.geometry import Polygon import folium from streamlit_folium import folium_static def display_map(df, selected_states, selected_livestocks): if selected_states: df = df[df['SIG_KOR_NM'].isin(selected_states)] if 'ALL' not in selected_livestocks: df = df[df['property_type_name'].isin(selected_livestocks)] color_mapping = { 'Unknown': 'black', 'chicken': 'green', # 修正拼写错误 'pig': 'pink', 'cow': 'orange' } if not df.empty: df['geometry'] = df['geometry_coordinates'].apply( lambda x: Polygon(ast.literal_eval(x)[0]) if pd.notnull(x) else None ) map = folium.Map(location=[35.4681593,128.4765802], zoom_start=1, scrollWheelZoom=False, tiles='CartoDB positron') for _, row in df.iterrows(): if row['geometry'] is not None and row['geometry'].is_valid: property_type_name = row['property_type_name'] folium.GeoJson( row['geometry'], style_function=lambda x, pt=property_type_name: { 'color': color_mapping.get(pt, 'gray'), 'fillColor': color_mapping.get(pt, 'gray') } ).add_to(map) folium_static(map) else : map = folium.Map(location=[35.4681593,128.4765802], zoom_start=7, scrollWheelZoom=False, tiles='CartoDB positron') return map
注意:原代码中
color_mapping里的chiecken存在拼写错误,已修正为chicken,避免牲畜类型匹配失败。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

