matplotlib 如何使用适当的文本旋转来注解回归线

yrdbyhpb  于 10个月前  发布在  其他
关注(0)|答案(1)|浏览(148)

我有下面的代码片段,可以通过图上的点集合绘制一条最佳拟合线,并使用相应的R2值对其进行注解:

import matplotlib.pyplot as plt
import numpy as np
import scipy.stats

x = 50 * np.random.rand(20) + 50
y = 200 * np.random.rand(20)
plt.plot(x, y, 'o')

# k, n = np.polyfit(x, y, 1)
k, n, r, _, _ = scipy.stats.linregress(x, y)
line = plt.axline((0, n), slope=k, color='blue')
xy = line.get_xydata()
plt.annotate(
    f'$R^2={r**2:.3f}$',
    (xy[0] + xy[-1]) // 2,
    xycoords='axes fraction',
    ha='center', va='center_baseline',
    rotation=k, rotation_mode='anchor',
)

plt.show()

字符串
我已经尝试了各种不同的(x,y)对,不同的xycoordsannotate中的其他关键字参数,但我无法让注解正确地出现在我想要的地方。如何让文本注解正确地旋转出现在行的上方,位于行的中点或两端?

dfuffjeb

dfuffjeb1#

1.标注坐标

我们不能在这里使用xydata计算坐标,因为axline()只是返回dummy xydata(可能是由于matplotlib内部绘制无限直线的方式):

print(line.get_xydata())
# array([[0., 0.],
#        [1., 1.]])

字符串
相反,我们可以根据xlim()计算文本坐标:

xmin, xmax = plt.xlim()
xtext = (xmin + xmax) // 2
ytext = k*xtext + n


请注意,这些是数据坐标,因此它们应该与xycoords='data'一起使用,而不是'axes fraction'

2.标注Angular

我们不能纯粹从线点计算Angular ,因为Angular 还取决于轴限制和图形尺寸(例如,想象6x4图形与2x8图形中所需的旋转Angular )。
相反,我们应该normalize the calculation to both scales来获得正确的视觉旋转:


的数据

rs = np.random.RandomState(0)
x = 50 * rs.rand(20) + 50
y = 200 * rs.rand(20)
plt.plot(x, y, 'o')

# save ax and fig scales
xmin, xmax = plt.xlim()
ymin, ymax = plt.ylim()
xfig, yfig = plt.gcf().get_size_inches()

k, n, r, _, _ = scipy.stats.linregress(x, y)
plt.axline((0, n), slope=k, color='blue')

# restore x and y limits after axline
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)

# find text coordinates at midpoint of regression line
xtext = (xmin + xmax) // 2
ytext = k*xtext + n

# find run and rise of (xtext, ytext) vs (0, n)
dx = xtext
dy = ytext - n

# normalize to ax and fig scales
xnorm = dx * xfig / (xmax - xmin)
ynorm = dy * yfig / (ymax - ymin)

# find normalized annotation angle in radians
rotation = np.rad2deg(np.arctan2(ynorm, xnorm))

plt.annotate(
    f'$R^2={r**2:.3f}$',
    (xtext, ytext), xycoords='data',
    ha='center', va='bottom',
    rotation=rotation, rotation_mode='anchor',
)

相关问题