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

Plotly Express中正确使用custom_data并通过点击事件获取国家名称的方法及错误解决

解决Plotly custom_data报错并实现地图点击显示国家名称

错误原因分析

我之前也碰到过这个问题,你遇到的ValueError是因为Plotly Express里的custom_data参数要求传入列名的列表,而不是单个字符串。当你直接传"location"时,Plotly会把它当成字符序列来解析,试图寻找不存在的custom_data_0列(本质是把单个字符串拆成了字符级的迭代项),所以才会报错。只要把单个列名用列表包裹就能解决。

修复后的基础代码

先修正custom_data的写法,这一步就能解决报错问题:

import pandas as pd
import plotly.express as px

def vaccination_lastest_date_by_country(dataframe):
    '''group the data by location and get last date data'''
    return dataframe.groupby('location').last().reset_index()

vaccination_data = pd.read_csv('vaccinations.csv')
df = pd.DataFrame(vaccination_data)
country_lastest_vaccination = vaccination_lastest_date_by_country(df)

df_vaccination_by_country = country_lastest_vaccination\
.sort_values(by='total_vaccinations_per_hundred', ascending=True)

def group_vaccination(x):
    if x < 40:
        return f'0~0.4'
    elif x < 80:
        return f'0.4~0.8'
    elif x < 120:
        return f'0.8~1.2'
    elif x < 160:
        return f'1.2~1.6'
    elif x < 200:
        return f'1.6~2'
    else:
        return f'2 above'

df_vaccination_by_country['Vaccination doses per person'] = df_vaccination_by_country\
['total_vaccinations_per_hundred'].apply(group_vaccination)

colors = ['#edf8e9','#c7e9c0','#bae4b3','#74c476','#31a354','#006d2c']

# 修正custom_data为列表形式
fig_map = px.choropleth(
    df_vaccination_by_country, 
    locations="iso_code", 
    color="Vaccination doses per person", 
    hover_name="location", 
    color_discrete_sequence=colors, 
    custom_data = ["location"]  # 这里改成列表
) 

fig_map.update_layout(autosize=False, width= 1200, height=800)

实现点击地图显示国家名称

下面分两种常用场景实现点击交互功能:

场景1:在Jupyter Notebook/JupyterLab中使用

用plotly.graph_objects.FigureWidget绑定点击事件,适合做交互式分析:

import plotly.graph_objects as go
from IPython.display import display, Markdown

# 将px生成的图转为可交互的FigureWidget
fig_widget = go.FigureWidget(fig_map)

# 定义点击事件处理函数
def handle_click(trace, points, state):
    if points.point_inds:
        # 从custom_data中提取国家名称
        country_name = points.customdata[0][0]
        print(f"点击了:{country_name}")
        # 在Notebook中优雅显示结果
        display(Markdown(f"### 你点击的国家:**{country_name}**"))

# 给地图图层绑定点击事件
fig_widget.data[0].on_click(handle_click)

# 显示交互地图
fig_widget

场景2:用Dash构建Web应用(适合生产部署)

如果要做可分享的Web页面,用Dash来实现更合适:

from dash import Dash, dcc, html, Input, Output

app = Dash(__name__)

# 构建页面布局:地图+结果显示区
app.layout = html.Div([
    dcc.Graph(id='choropleth-map', figure=fig_map),
    html.Div(
        id='click-output', 
        style={'margin-top': 20, 'font-size': 20, 'text-align': 'center'}
    )
])

# 定义点击回调逻辑
@app.callback(
    Output('click-output', 'children'),
    Input('choropleth-map', 'clickData')
)
def display_click_result(clickData):
    if clickData is None:
        return "点击地图上的国家查看名称"
    # 从clickData中提取custom_data里的国家名称
    country_name = clickData['points'][0]['customdata'][0]
    return f"你点击的国家是:{country_name}"

if __name__ == '__main__':
    app.run_server(debug=True)

补充小技巧

  • 你可以在custom_data里添加多个列,比如custom_data=["location", "total_vaccinations_per_hundred"],这样点击时能一次性获取更多数据,方便后续扩展功能。
  • 如果只是临时需要获取国家名称,也可以直接从clickData['points'][0]['hovertext']提取,但用custom_data更灵活,不受hover内容修改的影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 09:32:48