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
相关产品推荐
相关产品推荐

