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

如何为Plotly环形饼图添加环形分布的刻度标签?

问题

现有一段用Plotly生成环形饼图(甜甜圈图)的代码:

import plotly.graph_objects as go


def main():
    labels = ["Yale blue", "Lemon chiffon",
              "Naples yellow", "Sandy brown", "Tomato"]
    values = [14, 15, 15, 18, 19]
    colors = ["#0D3B66", "#FAF0CA", "#F4D35E", "#EE964B", "#F95738"]
    fig = go.Figure(data=[go.Pie(labels=labels,
                                 values=values,
                                 hole=.7,
                                 direction="clockwise",
                                 sort=False)])
    fig.update_traces(marker=dict(colors=colors))
    fig.show()


if __name__ == "__main__":
    main()

需要为该图表添加12个环形分布的标签:0点位置显示“1”,1点位置显示“2”,依此类推。期望实现如下形式的函数完成此功能:

def add_circular_labels(fig: go.Figure,
                        labels: List[str]):
    ...
add_circular_labels(fig, ["1", "2", ..., "12"])

解决方案

通过计算每个标签的极坐标位置,将其作为注释添加到图表中即可实现环形分布的标签。以下是完整实现:

实现add_circular_labels函数

import math
from typing import List
import plotly.graph_objects as go


def add_circular_labels(fig: go.Figure, labels: List[str]):
    # 标签分布的半径(比甜甜圈外半径稍大,避免重叠)
    radius = 1.1
    num_labels = len(labels)
    # 每个标签的角度间隔(弧度制)
    angle_step = 2 * math.pi / num_labels

    for idx, label in enumerate(labels):
        # 计算当前标签的角度:0点位置对应-90度(Plotly极坐标默认0度在右侧)
        angle = -math.pi/2 + idx * angle_step
        # 转换为笛卡尔坐标
        x = radius * math.cos(angle)
        y = radius * math.sin(angle)

        # 添加标签注释
        fig.add_annotation(
            x=x,
            y=y,
            text=label,
            showarrow=False,
            font=dict(size=14, color="#333333"),
            xanchor="center",
            yanchor="middle"
        )

    # 调整布局,确保标签完整显示
    fig.update_layout(
        margin=dict(l=40, r=40, t=40, b=40),
        xaxis=dict(visible=False),
        yaxis=dict(visible=False)
    )

整合到原代码

修改后的完整代码如下:

import math
from typing import List
import plotly.graph_objects as go


def add_circular_labels(fig: go.Figure, labels: List[str]):
    radius = 1.1
    num_labels = len(labels)
    angle_step = 2 * math.pi / num_labels

    for idx, label in enumerate(labels):
        angle = -math.pi/2 + idx * angle_step
        x = radius * math.cos(angle)
        y = radius * math.sin(angle)

        fig.add_annotation(
            x=x,
            y=y,
            text=label,
            showarrow=False,
            font=dict(size=14, color="#333333"),
            xanchor="center",
            yanchor="middle"
        )

    fig.update_layout(
        margin=dict(l=40, r=40, t=40, b=40),
        xaxis=dict(visible=False),
        yaxis=dict(visible=False)
    )


def main():
    labels = ["Yale blue", "Lemon chiffon",
              "Naples yellow", "Sandy brown", "Tomato"]
    values = [14, 15, 15, 18, 19]
    colors = ["#0D3B66", "#FAF0CA", "#F4D35E", "#EE964B", "#F95738"]
    fig = go.Figure(data=[go.Pie(labels=labels,
                                 values=values,
                                 hole=.7,
                                 direction="clockwise",
                                 sort=False)])
    fig.update_traces(marker=dict(colors=colors))
    
    # 添加12个环形标签
    add_circular_labels(fig, [str(i) for i in range(1, 13)])
    
    fig.show()


if __name__ == "__main__":
    main()

关键细节

  • 坐标计算:Plotly极坐标默认0度在右侧,要让顶部(0点位置)显示第一个标签,需将起始角度设为-math.pi/2(-90度),再按顺时针间隔分配位置。
  • 半径调整:radius=1.1保证标签在甜甜圈外侧,可根据图表大小自行修改。
  • 布局优化:隐藏坐标轴并设置边距,防止标签被截断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 11:58:24