<p>这里的想法是在图中画一条方程<code>y=m*x+y0</code>的线。这可以通过将最初在轴坐标中给出的水平线转换为数据坐标、根据直线方程应用仿射2D转换并转换回屏幕坐标来实现</p>
<p>这里的优点是,您根本不需要知道轴的限制。您还可以自由缩放或平移绘图;该线将始终保持在轴边界内。因此,它有效地实现了从-infinity到+infinity的行</p>
<pre><code>import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms
def axaline(m,y0, ax=None, **kwargs):
if not ax:
ax = plt.gca()
tr = mtransforms.BboxTransformTo(
mtransforms.TransformedBbox(ax.viewLim, ax.transScale)) + \
ax.transScale.inverted()
aff = mtransforms.Affine2D.from_values(1,m,0,0,0,y0)
trinv = ax.transData
line = plt.Line2D([0,1],[0,0],transform=tr+aff+trinv, **kwargs)
ax.add_line(line)
x = np.random.rand(20)*6-0.7
y = (np.random.rand(20)-.5)*4
c = (x > 3).astype(int)
fig, ax = plt.subplots()
ax.scatter(x,y, c=c, cmap="bwr")
# draw y=m*x+y0 into the plot
m = 0.4; y0 = -1
axaline(m,y0, ax=ax, color="limegreen", linewidth=5)
plt.show()
</code></pre>
<p><a href="https://i.stack.imgur.com/yvNcg.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/yvNcg.png" alt="enter image description here"/></a></p>
<p>虽然这个解决方案乍一看有点复杂,但人们不需要完全理解它。只需将<code>axaline</code>函数复制到代码中并按原样使用即可</p>
<p/><hr/>
为了使自动更新在不进行转换的情况下工作,可以添加回调,以便在每次绘图中发生更改时重置转换。
<pre><code>import numpy as np
import matplotlib.pyplot as plt
from matplotlib import transforms
class axaline():
def __init__(self, m,y0, ax=None, **kwargs):
if not ax: ax = plt.gca()
self.ax = ax
self.aff = transforms.Affine2D.from_values(1,m,0,0,0,y0)
self.line = plt.Line2D([0,1],[0,0], **kwargs)
self.update()
self.ax.add_line(self.line)
self.ax.callbacks.connect('xlim_changed', self.update)
self.ax.callbacks.connect('ylim_changed', self.update)
def update(self, evt=None):
tr = ax.transAxes - ax.transData
trinv = ax.transData
self.line.set_transform(tr+self.aff+trinv)
x = np.random.rand(20)*6-0.7
y = (np.random.rand(20)-.5)*4
c = (x > 3).astype(int)
fig, ax = plt.subplots()
ax.scatter(x,y, c=c, cmap="bwr")
# draw y=m*x+y0 into the plot
m = 0.4; y0 = -1
al = axaline(m,y0, ax=ax, color="limegreen", linewidth=5)
plt.show()
</code></pre>