You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:50:04