Plotly图表按大洲分组Y轴并显示组标题的布局设置咨询
实现Y轴按大洲分组并显示大洲名称
Plotly没有直接配置Y轴分组的内置选项,需要通过数据预处理排序+自定义刻度+添加分隔线与注释来实现,具体步骤如下:
1. 数据预处理:按大洲分组排序国家
先保留国家对应的大洲信息,按大洲分组后对组内国家排序,确保Y轴上同大洲的国家连续排列:
import pandas as pd import plotly.graph_objects as go from plotly import data df = data.gapminder() df = df.loc[df.year.isin([1987, 2007])] # 筛选目标国家并关联大洲信息,按人口排序 country_continent = ( df.loc[df.year == 2007] .sort_values(by=["pop"], ascending=True)[["country", "continent"]] .drop_duplicates() )[5:-10] # 按大洲分组,整理每个大洲的国家列表 grouped_countries = country_continent.groupby("continent")["country"].apply(list).to_dict() # 合并成按大洲排序的完整国家列表 sorted_countries = [] continent_order = list(grouped_countries.keys()) for continent in continent_order: sorted_countries.extend(grouped_countries[continent])
2. 重新构建可视化数据
按照排序后的国家列表生成绘图所需的x/y/颜色等数据:
data_dict = {"x": [], "y": [], "colors": [], "years": []} for country in sorted_countries: data_dict["x"].extend( [ df.loc[(df.year == 1987) & (df.country == country)]["pop"].values[0], df.loc[(df.year == 2007) & (df.country == country)]["pop"].values[0], None, ] ) data_dict["y"].extend([country, country, None]) data_dict["colors"].extend(["cyan", "darkblue", "white"]) data_dict["years"].extend(["1987", "2007", None])
3. 配置布局:添加分组分隔线与大洲名称注释
通过layout.shapes添加分组间的水平分隔线,用layout.annotations在每个分组顶部插入大洲名称,同时绑定Y轴刻度与排序后的国家:
fig = go.Figure( data=[ go.Scatter( x=data_dict["x"], y=data_dict["y"], mode="lines", marker=dict(color="grey"), ), go.Scatter( x=data_dict["x"], y=data_dict["y"], text=data_dict["years"], mode="markers", marker=dict( color=data_dict["colors"], symbol=["square", "circle", "circle"] * len(sorted_countries), size=16 ), hovertemplate="""Country: %{y} <br> Population: %{x} <br> Year: %{text} <br><extra></extra>""" ) ] ) # 计算每个国家在Y轴的索引位置,用于定位分隔线和注释 y_pos = {country: idx for idx, country in enumerate(sorted_countries)} shapes = [] annotations = [] current_pos = 0 for continent in continent_order: country_list = grouped_countries[continent] # 计算分组的起始、结束索引 start_pos = current_pos end_pos = current_pos + len(country_list) - 1 # 添加垂直显示的大洲名称注释,放在分组中间位置 annotations.append( dict( xref="paper", x=0, y=(start_pos + end_pos)/2, text=f"<b>{continent}</b>", showarrow=False, font=dict(size=14), textangle=-90 ) ) # 给除最后一个大洲外的分组添加底部分隔线 if continent != continent_order[-1]: shapes.append( dict( type="line", xref="paper", x0=0, x1=1, yref="y", y0=end_pos + 0.5, y1=end_pos + 0.5, line=dict(color="black", width=2) ) ) current_pos += len(country_list) # 更新布局参数 fig.update_layout( yaxis=dict( tickmode="array", tickvals=list(range(len(sorted_countries))), ticktext=sorted_countries, tickfont=dict(size=10) ), shapes=shapes, annotations=annotations, height=800 # 调整高度适配多分组显示 ) fig.show()
关键说明
- 数据排序是分组显示的基础,必须保证同大洲国家在Y轴上连续排列
- 用
shapes绘制的水平分隔线可以清晰区分不同大洲分组 - 垂直排版的大洲名称注释通过
textangle=-90实现,放在分组中间位置更直观 - Y轴刻度通过
tickvals和ticktext绑定排序后的国家列表,确保对应关系准确
内容的提问来源于stack exchange,提问作者Johann
相关产品推荐
相关产品推荐

