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

如何在非均匀刻度的极坐标图中垂直旋转所有刻度标签?

解决方案:动态调整旋转角度与锚点

直接围绕原点旋转会导致所有标签统一偏移,忽略了各自的刻度角度,这就是90度旋转后标签转出画布的原因。正确的做法是针对每个刻度的自身角度,单独调整旋转参数和文本锚点,让标签始终朝向外侧且垂直于径向。

核心修改代码

替换原函数中plt.xticks()及后续的循环部分为以下代码:

plt.xticks(
    np.concatenate(tuple(list(thetas.values()))),
    labels,
    transform_rotates_text=False  # 关闭自动旋转,手动控制
)

# 获取所有刻度的极角(转换为角度)
tick_thetas = np.concatenate(tuple(list(thetas.values()))) * 180 / np.pi

for tick, theta_deg in zip(plt.xticks()[1], tick_thetas):
    # 计算旋转角度:让标签垂直于径向,朝向外侧
    rotate_angle = theta_deg - 90
    # 围绕刻度自身位置旋转,避免偏移
    tick.set_transform(
        tick.get_transform() + mpl.transforms.Affine2D().rotate_deg_around(
            tick.get_position()[0], tick.get_position()[1], rotate_angle
        )
    )
    # 根据象限设置锚点,确保文本向外排列
    if 0 <= theta_deg < 90:
        tick.set_ha('right')
        tick.set_va('bottom')
    elif 90 <= theta_deg < 180:
        tick.set_ha('right')
        tick.set_va('top')
    elif 180 <= theta_deg < 270:
        tick.set_ha('left')
        tick.set_va('top')
    else:  # 270°-360°
        tick.set_ha('left')
        tick.set_va('bottom')

修改说明

  1. 关闭自动旋转:transform_rotates_text=False避免Matplotlib默认的极坐标旋转干扰自定义设置。
  2. 基于刻度位置旋转:不再围绕原点旋转,而是以每个刻度的实际坐标点为旋转中心,确保标签不会偏离刻度线。
  3. 动态计算旋转角度:根据刻度的极角计算旋转值,保证文本方向与径向垂直。
  4. 象限锚点适配:根据刻度所在象限调整文本对齐方式,让标签始终向外,避免被画布截断。

修改后的完整draw_radar函数

def draw_radar(data, colour_letters, person_name=""):
    """Draw the graph.

    Based substantially on a SO thread
    """
    # not really sure why -1, but if you don't you get an empty segment
    num_areas = len(data) - 1
    running_total = 0
    thetas = {}
    for key, value in data.items():
        this_area_num_points = len(value)
        this_area_theta = ((2 * np.pi) / num_areas) / (this_area_num_points)
        thetas[key] = []
        for i in range(len(value)):
            thetas[key].append((i * this_area_theta) + running_total)
        running_total += (2 * np.pi) / num_areas

    labels = []
    for key, value in data.items():
        for area, score in value.items():
            labels.append(f"{score} {key}: {area}")

    for name, theta_list in thetas.items():
        individual_scores = list(data[name].values())
        colour = random.choice(colour_letters)
        if len(theta_list) > 1:
            plt.polar(theta_list, individual_scores, c=colour, label=name)
        elif len(theta_list) == 1:
            plt.scatter(theta_list, individual_scores, c=colour, label=name)
    plt.yticks(np.arange(-5, 5), [""] * 5 + list(range(5)))
    
    # 修改后的刻度设置部分
    plt.xticks(
        np.concatenate(tuple(list(thetas.values()))),
        labels,
        transform_rotates_text=False
    )
    tick_thetas = np.concatenate(tuple(list(thetas.values()))) * 180 / np.pi
    for tick, theta_deg in zip(plt.xticks()[1], tick_thetas):
        rotate_angle = theta_deg - 90
        tick.set_transform(
            tick.get_transform() + mpl.transforms.Affine2D().rotate_deg_around(
                tick.get_position()[0], tick.get_position()[1], rotate_angle
            )
        )
        if 0 <= theta_deg < 90:
            tick.set_ha('right')
            tick.set_va('bottom')
        elif 90 <= theta_deg < 180:
            tick.set_ha('right')
            tick.set_va('top')
        elif 180 <= theta_deg < 270:
            tick.set_ha('left')
            tick.set_va('top')
        else:
            tick.set_ha('left')
            tick.set_va('bottom')
    
    if person_name:
        plt.title = f"Competency for {person_name}"
    plt.savefig("radar.png")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 05:39:49