Python 适当旋转标签并将其与matplotlib对齐

Python 适当旋转标签并将其与matplotlib对齐,python,matplotlib,Python,Matplotlib,下面的代码将一些点放置在平面上,并从中心到每个点绘制一条线。对于每个点,都有一个标签,并希望将标签放在该点之后。因此,从中心,我们看到一条线,然后是一个点,然后是一个文本。我想把标签放在同一条线的斜率上 目前,我有这段代码,但正如您所看到的,旋转后的文本没有正确对齐。我怎样才能解决这个问题 import matplotlib.pyplot as plt import numpy as np from math import * a = np.array([ [-0.108,0.414], [0.

下面的代码将一些点放置在平面上,并从中心到每个点绘制一条线。对于每个点,都有一个标签,并希望将标签放在该点之后。因此,从中心,我们看到一条线,然后是一个点,然后是一个文本。我想把标签放在同一条线的斜率上

目前,我有这段代码,但正如您所看到的,旋转后的文本没有正确对齐。我怎样才能解决这个问题

import matplotlib.pyplot as plt
import numpy as np
from math import *
a = np.array([
[-0.108,0.414],
[0.755,-0.152],
[0.871,-0.039],
],)
labels = ["XXXXXXX", "YYYYYY", "ZZZZZZZ"]

x, y = a.T
plt.scatter(x, y)
plt.xlim(-1,1)
plt.ylim(-1,1)

ax = plt.axes()
for i in range(a.shape[0]):
   px = a[i,0]
   py = a[i,1]
   ax.arrow(0, 0, px, py, head_width=0, head_length=0.1, length_includes_head=True)
   angle = degrees(atan(py/px))
   ax.annotate(labels[i], (px, py), rotation=angle)

plt.grid(True)
plt.show()

更新:

我使用了建议和修改的解决方案

text_plot_location = np.array([0.51,0.51])
trans_angle = plt.gca().transData.transform_angles(np.array((45,)),text_plot_location.reshape((1,2)))[0]
ax.annotate(labels[i], (px, py), rotation=text_plot_location)

然而,我得到了这个错误,
TypeError:unhabable type:'numpy.ndarray'
由@mapf创建的链接有点干净,但这是我想到的:

导入matplotlib.pyplot作为plt
将numpy作为np导入
a=np.array([
[-0.108,0.414],
[0.755,-0.152],
[0.871,-0.039],
],)
标签=[“XXXXXXX”、“yyyyy”、“ZZZZZZZ”]
x、 y=a.T
图,ax=plt.子批次()
最大散射(x,y)
ax.set_xlim(-1,1)
ax.set_ylim(-1,1)
直线,=最大曲线图(*a.T)
对于枚举(zip(标签,a))中的jdx(标签,点):
#找到最近的点
tmp=np.linalg.norm(a点,轴=1)
idx=np.argsort(tmp)[1]
其他=a[idx]
#计算角度
度=np.角(复数(*(点-其他)))
度=np.rad2deg(度)
ax.注释(标签、点、旋转=度、,
ha='左',va='基线',
transform=ax.transData)
ax.grid(真)
图2(图3)


我不知道为什么角度与直线不完全匹配。

您在更新中犯了一个简单的错误。您需要将
trans\u angle
传递到
rotation
关键字,而不是
text\u plot\u location
,但是,我不确定结果是否是您要查找的

import matplotlib.pyplot as plt
import numpy as np
from math import *
a = np.array([
[-0.108,0.414],
[0.755,-0.152],
[0.871,-0.039],
],)
labels = ["XXXXXXX", "YYYYYY", "ZZZZZZZ"]

x, y = a.T
plt.scatter(x, y)
plt.xlim(-1,1)
plt.ylim(-1,1)

ax = plt.axes()
for i in range(a.shape[0]):
    px = a[i, 0]
    py = a[i, 1]
    ax.arrow(0, 0, px, py, head_width=0, head_length=0.1,
             length_includes_head=True)
    text_plot_location = np.array([0.51, 0.51])
    angle = degrees(atan(py / px))
    trans_angle = plt.gca().transData.transform_angles(
        np.array((angle,)), text_plot_location.reshape((1, 2))
    )[0]
    ax.annotate(labels[i], (px, py), rotation=trans_angle)

plt.grid(True)
plt.show()

不太理想,但离你想要的有点近。缺点是文本偏移的任意值为30点,该值适用于给定标签,但需要针对更长或更短的标签进行调整

import matplotlib.pyplot as plt
import numpy as np
from math import *
a = np.array([[-0.108,0.414],[0.755,-0.152],[0.871,-0.039]])
labels = ["XXXXXXX", "YYYYYY", "ZZZZZZZ"]

x, y = a.T
plt.scatter(x, y)
plt.xlim(-1,1)
plt.ylim(-1,1)

ax = plt.axes()
for i in range(a.shape[0]):
   px = a[i,0]
   py = a[i,1]
   ax.arrow(0, 0, px, py, head_width=0, head_length=0.1, length_includes_head=True)
   angle = atan(py/px)
   d = (-1 if px < 0 else 1) * 30
   ax.annotate(labels[i], (px, py), rotation=degrees(angle), textcoords="offset points", 
               xytext=(d*cos(angle), d*sin(angle)), 
               verticalalignment='center', horizontalalignment='center')

plt.grid(True)
plt.show()
导入matplotlib.pyplot作为plt
将numpy作为np导入
从数学导入*
a=np.数组([-0.108,0.414],[0.755,-0.152],[0.871,-0.039])
标签=[“XXXXXXX”、“yyyyy”、“ZZZZZZZ”]
x、 y=a.T
plt.散射(x,y)
plt.xlim(-1,1)
plt.ylim(-1,1)
ax=plt.axs()
对于范围内的i(a.shape[0]):
px=a[i,0]
py=a[i,1]
最大箭头(0,0,px,py,头部宽度=0,头部长度=0.1,长度包括头部=True)
角度=atan(py/px)
d=(-1,如果px<0,则为1)*30
ax.注释(标签[i],(px,py),旋转=度(角度),textcoords=“偏移点”,
xytext=(d*cos(角度),d*sin(角度)),
垂直对齐=中心,水平对齐=中心)
plt.grid(真)
plt.show()

这是否回答了您的问题?这将使标签位于线上方。在我的最后一段代码中,我有很多点,如果我把标签放在线条上面,那么对于那些有小角度的线条来说,表示方式就不好了。我理解,但是你应该能够控制文本相对于线条的偏移量。我更新了帖子。