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

Matplotlib.pyplot.annotate中offset points参数出现异常结果求助

问题:Matplotlib标注箭头长度与方向异常

我使用以下代码生成一幅包含360度范围内24个“小时”标记的正弦曲线图表。每个“小时”都添加了标注,但箭头长度逐渐缩短,甚至方向也不正确。X轴范围为360度,Y轴范围为70度。print语句验证了6点和18点的箭头参数一致且应为垂直方向,但实际图表显示并非如此。使用的Matplotlib版本为3.9.2,Numpy版本为2.1.1。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

arrow_style = {'arrowstyle': '->'}

def make_plot():

    fig, ax = plt.subplots()
    ax.axis([0,+360,-35,+35])
    ax.set(xlabel = 'X (degrees)', ylabel = 'Y (degrees)', title='Vanishing arrow length example')

    degree = np.pi / 180.0  # degrees to radians
    arrow_angle = 72.0      # degrees
    arrow_length = 27.0
    eps = 23.43927945

    eps_x = np.linspace(0, 360, 200)
    eps_y = -eps * np.sin(2 * np.pi * eps_x / 360)
    ax.plot(eps_x, eps_y, 'r')

    hr_x = np.linspace(0, 360, 25)
    hr_y = -eps * np.sin(2 * np.pi * hr_x / 360)

    i = 0
    for x in hr_x:
        ax.plot(hr_x[i], hr_y[i],'bo')
        if hr_y[i] > 0 and arrow_angle > 0: arrow_angle = -75   # degrees
        arrow_x = np.cos(arrow_angle*degree) * arrow_length
        arrow_y = np.sin(arrow_angle*degree) * arrow_length
        ax.annotate(str(i), xy=(hr_x[i], hr_y[i]), xytext=(arrow_x, arrow_y), \
                    xycoords='data', textcoords='offset points', arrowprops=arrow_style)
        print("arrow_x {:.2f}  arrow_y {:.2f}  arrow_angle {:.1f} at {} hours" \
              .format(arrow_x, arrow_y, arrow_angle, i))

        if hr_y[i] <= 0: arrow_angle += 3.0
        if hr_y[i] > 0:  arrow_angle -= 3.0
        i += 1

    ax.grid()
    ax.axhline(0.0)
    ax.axvline(180.0)
    plt.show()

    return fig

make_plot().savefig('vanishing_arrow_length.png')

问题原因与修复

核心错误

  1. 坐标系统混淆:textcoords='offset points'表示文本位置是相对于xy点的屏幕像素偏移,而你计算的arrow_x/arrow_y是基于数据坐标的偏移,两者单位不匹配,导致箭头长度随图表缩放或坐标范围变化而失真。
  2. 文本位置设置错误:xytext=(arrow_x, arrow_y)被设置为绝对屏幕点坐标,而非相对于标注点的偏移,导致箭头方向完全错误。

修改后的代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

arrow_style = {'arrowstyle': '->'}

def make_plot():

    fig, ax = plt.subplots()
    ax.axis([0,+360,-35,+35])
    ax.set(xlabel = 'X (degrees)', ylabel = 'Y (degrees)', title='Fixed arrow length example')

    degree = np.pi / 180.0  # degrees to radians
    arrow_angle = 72.0      # degrees
    arrow_length = 27.0
    eps = 23.43927945

    eps_x = np.linspace(0, 360, 200)
    eps_y = -eps * np.sin(2 * np.pi * eps_x / 360)
    ax.plot(eps_x, eps_y, 'r')

    hr_x = np.linspace(0, 360, 25)
    hr_y = -eps * np.sin(2 * np.pi * hr_x / 360)

    i = 0
    for x in hr_x:
        ax.plot(hr_x[i], hr_y[i],'bo')
        # 修正角度切换逻辑:确保在曲线上下方时箭头方向正确
        if hr_y[i] > 0 and arrow_angle > 0:
            arrow_angle = -75
        elif hr_y[i] <= 0 and arrow_angle < 0:
            arrow_angle = 72
        
        # 计算基于数据坐标的箭头偏移
        arrow_x = np.cos(arrow_angle * degree) * arrow_length
        arrow_y = np.sin(arrow_angle * degree) * arrow_length
        
        # 文本位置为标注点加上偏移量,使用data坐标系统
        text_x = hr_x[i] + arrow_x
        text_y = hr_y[i] + arrow_y
        
        ax.annotate(str(i), 
                    xy=(hr_x[i], hr_y[i]), 
                    xytext=(text_x, text_y),
                    xycoords='data', 
                    textcoords='data', 
                    arrowprops=arrow_style)
        
        print("arrow_x {:.2f}  arrow_y {:.2f}  arrow_angle {:.1f} at {} hours" \
              .format(arrow_x, arrow_y, arrow_angle, i))

        # 逐步调整箭头角度
        if hr_y[i] <= 0:
            arrow_angle += 3.0
        else:
            arrow_angle -= 3.0
        i += 1

    ax.grid()
    ax.axhline(0.0)
    ax.axvline(180.0)
    plt.show()

    return fig

make_plot().savefig('fixed_arrow_length.png')

关键修改说明

  • 将textcoords改为'data',使文本位置和标注点使用同一数据坐标系统,确保箭头长度和方向不受图表缩放影响。
  • 调整xytext的计算方式:text_x = hr_x[i] + arrow_x,让文本位置是标注点加上箭头方向的偏移量,而非绝对坐标。
  • 优化角度切换逻辑,避免在曲线上下方切换时出现角度突变,确保箭头方向平滑过渡。

修改后,6点和18点的箭头会正确显示为垂直方向,所有箭头长度保持一致,方向符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 15:08:11