python - 如何在没有溢出的情况下通过散点图画一条线

标签 python matplotlib

所以我目前正在 matplotlib 中绘制一个包含许多 xy 的散点图:

plt.scatter(x, y)

我想在这个散点图上画一条穿过整个图的线(即击中两个“边界”)我知道梯度和截距 - mc 在等式 y = mx +c 中。

我考虑过获取绘图的 4 个点(计算最小和最大散点 xy),并从中计算最小和最大坐标线然后绘图,但这看起来很复杂。考虑到这条线甚至可能不在“地 block ”内,有没有更好的方法来做到这一点?


散点图示例: enter image description here

从图中可以看出,四个边界坐标是褶皱状的:

  • 左下:-1,-2
  • 左上:-1,2
  • 右下:6,-2
  • 右上6,2

我现在有一条线,我需要绘制它不能超过这些边界,但如果它进入绘图必须触及两个边界点。

所以我可以检查当 x = -1 时 y 等于什么,然后检查该值是否在 -1 和 6 之间,如果线必须穿过左边界,那么绘制它,依此类推。


理想情况下,我会创建一条从 -infinity 到 infinity 的线,然后裁剪它以适合绘图。

最佳答案

这里的想法是在绘图中画一条方程 y=m*x+y0 的线。这可以通过将最初在轴坐标中给出的水平线转换为数据坐标,根据线方程应用 Affine2D 变换并转换回屏幕坐标来实现。

这里的优点是您根本不需要知道轴的限制。您也可以自由缩放或平移您的绘图;该线将始终位于轴边界内。因此,它有效地实现了从 -infinity 到 + inifinty 的直线。

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()

enter image description here

虽然这个解决方案乍一看有点复杂,但并不需要完全理解它。只需将 axaline 函数复制到您的代码中并按原样使用它。


为了在没有转换的情况下自动更新工作,可以添加回调,每次情节发生变化时都会重置转换。

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()

关于python - 如何在没有溢出的情况下通过散点图画一条线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49192667/

相关文章:

python - Easygui 中的滚动条?

python - python - 如何在python的csv文件中为每个基因保留x个最高人相关值的基因对?

python - 所有数字的总和

python - 如何在Python中使用ElementTree获取XML元素文本

python - 如何更改 Matplotlib 中刻度标签和轴标签之间的分隔

python - 逐帧可视化 3D-numpy-array

python - 使用QLineEdit.setText()可以卡住窗口,但是后台任务可以正常工作

python - matplotlib 中的中心多线图例

python - 使用 hlines 创建甘特图?

python - Matplotlib:循环中创建的第一个绘图未使用 rcParams 中指定的 'figsize' 保存