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

Plotly下拉切换选项时Choropleth地图无数据显示求助

解决Plotly Choropleth地图切换Description分类无数据的问题

问题背景

我正在尝试创建一张国际Choropleth地图,鼠标悬停在各国时可查看对应病例数与死亡数,并添加基于Description列的下拉框以切换不同分类。目前仅“All Descriptions”能正常显示数据,切换至其他选项时地图无任何数据。

数据信息

数据列:

Index(['Case#', 'Year', 'Date', 'Country', 'State', 'Description', 'deaths', 'Tesladriver', 'Teslaoccupant', 'Othervehicle', 'CyclistsPedsivolved', 'TSLAcyclpedsinvolved', 'Autopilotclaimed', 'VerifiedTeslaAutopilotDeaths', 'VerifiedTeslaAutopilotDeathsAllDeathsReportedtoNHTSASGO'], dtype='object')

数据示例:

array([[294, 2022, '1/17/2023', 'USA', 'CA', 'Collisions', 1, '1', '-', '-', 0, 1, 0, 0, 0], 
       [293, 2022, '45108', 'Canada', '-', 'Other Causes', 1, '1', '-', '-', 0, 1, 0, 0, 0], 
       [292, 2022, '45108', 'USA', 'WA', 'Other Causes', 1, '-', '1', '-', 0, 1, 0, 0, 0], 
       [291, 2022, '12/22/2022', 'USA', 'GA', 'Other Causes', 1, '1', '-', '-', 0, 1, 0, 0, 0], 
       [290, 2022, '12/19/2022', 'Canada', '-', 'Collisions', 1, '-', '-', '-', 1, 1, 0, 0, 0]], dtype=object)

原问题代码

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd


fig = make_subplots(rows=1, cols=1)


unique_descriptions = data['Description'].unique()


filtered_data = {description: data[data['Description'] == description] for description in unique_descriptions}


country_counts = {country: {desc: {'count': 0, 'deaths': 0} for desc in unique_descriptions} for country in data['Country'].unique()}


fig.add_trace(
    go.Choropleth(
        locations=data['Country'],
        z=[country_counts[country][desc]['count'] for country, desc in zip(data['Country'], data['Description'])],
        locationmode='country names',
        colorscale='YlOrRd',
        colorbar_title='Count',
        hovertemplate='<b>%{location}</b><br>Count: %{z}<br>Total Deaths: %{customdata}',
        customdata=[country_counts[country][desc]['deaths'] for country, desc in zip(data['Country'], data['Description'])],
        text=[country_counts[country][desc]['count'] for country, desc in zip(data['Country'], data['Description'])],
        textsrc='inside',
        visible=True  # Set the initial trace as visible
    )
)

dropdown_options = [
    dict(
        label='All Descriptions',
        method='update',
        args=[{'visible': [True] * len(fig.data)}],  # Show all traces
        args2=[{'title': 'Cases and Deaths by Country (Description: All Descriptions)'}]
    )
]


for description in unique_descriptions:


    for country in filtered_data[description]['Country'].unique():
        count = len(filtered_data[description][(filtered_data[description]['Country'] == country) & (filtered_data[description]['Description'] == description)])
        deaths = filtered_data[description][(filtered_data[description]['Country'] == country) & (filtered_data[description]['Description'] == description)]['deaths'].sum()
        country_counts[country][description]['count'] = count
        country_counts[country][description]['deaths'] = deaths


    fig.add_trace(
        go.Choropleth(
            locations=data['Country'],
            z=[country_counts[country][desc]['count'] for country, desc in zip(data['Country'], data['Description'])],
            locationmode='country names',
            colorscale='YlOrRd',
            colorbar_title='Count',
            hovertemplate='<b>%{location}</b><br>Count: %{z}<br>Total Deaths: %{customdata}',
            customdata=[country_counts[country][desc]['deaths'] for country, desc in zip(data['Country'], data['Description'])],
            text=[country_counts[country][desc]['count'] for country, desc in zip(data['Country'], data['Description'])],
            textsrc='inside',
            visible=False  # Set the trace as invisible initially
        )
    )


    dropdown_options.append(
        dict(
            label=description,
            method='update',
            args=[{'visible': [True if desc == description else False for desc in fig.data]}],  # Show only the corresponding trace
            args2=[{'title': f'Cases and Deaths by Country (Description: {description})'}]
        )
    )


fig.update_layout(
    title='Cases and Deaths by Country',
    updatemenus=[
        dict(
            type='dropdown',
            buttons=dropdown_options,
            direction='down',
            showactive=True,
            x=0.1,
            y=1.1
        )
    ],
    geo=dict(showframe=False, showcoastlines=True, projection_type='natural earth')
)

fig.update_layout(height=600)

fig.show()

问题根源

  1. Trace数据逻辑错误:每个Description对应的trace使用全量数据的locations,但z值仅匹配对应Description的行,其余行z为0,导致地图无法正确渲染。
  2. 下拉框可见性判断错误:将trace对象直接与Description字符串对比,筛选逻辑完全失效,无法正确显示对应trace。
  3. 数据初始化顺序颠倒:第一个"All Descriptions"的trace使用未计算的空统计值,后续循环才填充数据,逻辑顺序错误。

修正方案

  1. 提前聚合数据:按国家和Description分组计算病例数与死亡数,单独处理"All Descriptions"的全局统计。
  2. 每个Trace对应独立聚合数据:每个Description的trace仅使用该分类下的国家统计数据,确保locations与z值一一对应。
  3. 修正下拉框可见性逻辑:根据trace的索引控制显示,第一个trace对应全局数据,后续依次对应各Description。

修正后的代码

import plotly.graph_objects as go
import pandas as pd

# 1. 聚合全局数据(All Descriptions)
all_agg = data.groupby('Country').agg(
    count=('Case#', 'count'),
    deaths=('deaths', 'sum')
).reset_index()

# 2. 按Description分组聚合数据
unique_descriptions = data['Description'].unique()
desc_agg = {}
for desc in unique_descriptions:
    filtered_data = data[data['Description'] == desc]
    agg_result = filtered_data.groupby('Country').agg(
        count=('Case#', 'count'),
        deaths=('deaths', 'sum')
    ).reset_index()
    desc_agg[desc] = agg_result

# 3. 创建图表并添加Trace
fig = go.Figure()

# 添加全局数据Trace
fig.add_trace(go.Choropleth(
    locations=all_agg['Country'],
    z=all_agg['count'],
    locationmode='country names',
    colorscale='YlOrRd',
    colorbar_title='Case Count',
    hovertemplate='<b>%{location}</b><br>Case Count: %{z}<br>Total Deaths: %{customdata}',
    customdata=all_agg['deaths'],
    visible=True
))

# 添加各Description的Trace
for desc in unique_descriptions:
    agg_data = desc_agg[desc]
    fig.add_trace(go.Choropleth(
        locations=agg_data['Country'],
        z=agg_data['count'],
        locationmode='country names',
        colorscale='YlOrRd',
        colorbar_title='Case Count',
        hovertemplate='<b>%{location}</b><br>Case Count: %{z}<br>Total Deaths: %{customdata}',
        customdata=agg_data['deaths'],
        visible=False
    ))

# 4. 构建下拉框选项
dropdown_options = [
    dict(
        label='All Descriptions',
        method='update',
        args=[
            {'visible': [True] + [False]*len(unique_descriptions)},
            {'title': 'Cases and Deaths by Country (All Descriptions)'}
        ]
    )
]

for idx, desc in enumerate(unique_descriptions):
    # 生成可见性列表:仅对应索引的Trace显示
    visible_list = [False]*(len(unique_descriptions)+1)
    visible_list[idx+1] = True
    dropdown_options.append(
        dict(
            label=desc,
            method='update',
            args=[
                {'visible': visible_list},
                {'title': f'Cases and Deaths by Country (Description: {desc})'}
            ]
        )
    )

# 5. 更新布局
fig.update_layout(
    title='Cases and Deaths by Country',
    updatemenus=[
        dict(
            type='dropdown',
            buttons=dropdown_options,
            direction='down',
            showactive=True,
            x=0.1,
            y=1.1
        )
    ],
    geo=dict(showframe=False, showcoastlines=True, projection_type='natural earth'),
    height=600
)

fig.show()

内容的提问来源于stack exchange,提问作者Lior Broide

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:47:01