如何用 matplotlib 画一条线?

Posted

技术标签:

【中文标题】如何用 matplotlib 画一条线?【英文标题】:How to draw a line with matplotlib? 【发布时间】:2016-07-27 23:45:57 【问题描述】:

我找不到使用matplotlib Python 库绘制任意线的方法。它允许绘制水平线和垂直线(例如matplotlib.pyplot.axhlinematplotlib.pyplot.axvline),但我看不到如何通过(x1, y1)(x2, y2) 两个给定点绘制一条线。有办法吗?有没有简单的方法?

【问题讨论】:

matplotlib: extended line over 2 control points的可能重复 另见此处:***.com/questions/25676073/… 【参考方案1】:

根据@Alejandro 的回答:

如果您想在现有的Axes 中添加一条线(例如散点图),并且 您所知道的只是所需直线(例如回归线)的斜率和截距,以及 您希望它覆盖整个可见 X 范围(已计算),并且 你想使用面向对象的接口(不是pyplot)。

然后你可以这样做(ax 中的现有 Axes):

# e.g. slope, intercept, r_value, p_value, std_err = scipy.stats.linregress(xs, ys)
xmin, xmax = ax.get_xbound()
ymin = (xmin * slope) + intercept
ymax = (xmax * slope) + intercept
l = matplotlib.lines.Line2D([xmin, xmax], [ymin, ymax])
ax.add_line(l)

【讨论】:

【参考方案2】:

这将绘制一条穿过点 (-1, 1) 和 (12, 4) 的线,以及另一条穿过点 (1, 3) 和 (10, 2) 的线

x1 是第一行点的 x 坐标,y1 是同一行的 y 坐标 -- x1 和 y1 中的元素必须是顺序的。

x2 和 y2 与另一行相同。

import matplotlib.pyplot as plt
x1, y1 = [-1, 12], [1, 4]
x2, y2 = [1, 10], [3, 2]
plt.plot(x1, y1, x2, y2, marker = 'o')
plt.show()

我建议您花一些时间阅读/学习在非常丰富的 matplotlib 网站上找到的基本教程,以熟悉该库。

如果我不想要线段怎么办?


[编辑]:

如@thomaskeefe 所示,从 matplotlib 3.3 开始,为了方便起见,现在内置了:plt.axline((x1, y1), (x2, y2)),使以下内容过时。


没有直接的方法可以将线延伸到无穷远... matplotlib 将调整绘图的大小/重新缩放绘图,以便最远的点位于边界上,另一个位于内部,绘制线段有效;或者您必须选择要设置为可见的表面边界之外的点,并为 x 和 y 轴设置限制。

如下:

import matplotlib.pyplot as plt
x1, y1 = [-1, 12], [1, 10]
x2, y2 = [-1, 10], [3, -1]
plt.xlim(0, 8), plt.ylim(-2, 8)
plt.plot(x1, y1, x2, y2, marker = 'o')
plt.show()

【讨论】:

这不画线,它在给定点之间画线段。 是的,matplotlib 绘制线段......线条的绘制方式,你不能将线条延伸到无穷大。我更新了我的答案,为您提供了两种解决方法。 “线条的绘制方式,你不能将线条延伸到无穷大”——为什么不呢? axhlineaxvline 创建“无限”行。对我来说,您的解决方案的问题是我很可能需要通过所示区域内的点的线。当然,我可以创建一个长线段,其端点在所示区域之外,但这很不方便(我需要以某种方式计算端点)并且丑陋(我需要一条线,但我画了一个线段并尝试平移到让它看起来像一条线,计算我不需要的端点)。 这是一个在 matplotlib 邮件列表中提出的问题,我只是想在这里回答您的问题……抱歉,我帮不上忙,但我无法为产品添加功能!我试图通过解释 matplotlib 如何绘制来告诉你原因:matplotlib 主要绘制像素以呈现在印刷出版物上;它在其他方面并不是真正的***,但仍然试图使事情成为可能。也许您需要其他工具? 好的,谢谢。我只是不确定 matplotlib 是否有这个工具。在我最近的案例中,我试图了解平面上一些点对的行为,我想通过它们画线,看看这些线在哪里以及如何相交。【参考方案3】:

如果有人来到这里试图一次绘制多个片段,这里有一种方法。假设段由两个相同长度的二维数组定义,例如ab。我们想要在每个a[i]b[i] 之间绘制段。在这种情况下:

解决方案 1

ab_pairs = np.c_[a, b]
plt_args = ab_pairs.reshape(-1, 2, 2).swapaxes(1, 2).reshape(-1, 2)
ax.plot(*plt_args, ...)

示例:

np.random.seed(0)
n = 32
a = np.random.uniform(0, 1, (n, 2))
b = np.random.uniform(0, 1, (n, 2))

fig, ax = plt.subplots(figsize=(3, 3))
ab_pairs = np.c_[a, b]
ab_args = ab_pairs.reshape(-1, 2, 2).swapaxes(1, 2).reshape(-1, 2)

# segments
ax.plot(*ab_args, c='k')

# identify points: a in blue, b in red
ax.plot(*a.T, 'bo')
ax.plot(*b.T, 'ro')
plt.show()

解决方案 2

上面创建了许多matplotlib.lines.Line2D。如果您想要单行,我们可以通过在两对之间交错 NaN 来实现:

ax.plot(*np.c_[a, b, a*np.nan].reshape(-1, 2).T, ...)

示例:

# same init as example above, then

fig, ax = plt.subplots(figsize=(3, 3))

# segments (all at once)
ax.plot(*np.c_[a, b, a*np.nan].reshape(-1, 2).T, 'k')

# identify points: a in blue, b in red
ax.plot(*a.T, 'bo')
ax.plot(*b.T, 'ro')
plt.show()

(同上图)。

【讨论】:

【参考方案4】:

从 matplotlib 3.3 开始,您可以使用 plt.axline((x1, y1), (x2, y2)) 执行此操作。

【讨论】:

【参考方案5】:

只想在这里提另一个选项。

您可以使用 numpy.polyfit() 计算系数,并将系数提供给 numpy.poly1d()。该函数可以使用系数构造多项式,您可以在此处找到更多示例

https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.poly1d.html

假设给定两个数据点 (-0.3, -0.5) 和 (0.8, 0.8)

import numpy as np
import matplotlib.pyplot as plt

# compute coefficients
coefficients = np.polyfit([-0.3, 0.8], [-0.5, 0.8], 1) 

# create a polynomial object with the coefficients
polynomial = np.poly1d(coefficients)

# for the line to extend beyond the two points, 
# create the linespace using the min and max of the x_lim
# I'm using -1 and 1 here
x_axis = np.linspace(-1, 1)

# compute the y for each x using the polynomial
y_axis = polynomial(x_axis)

fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 1, 1])
axes.set_xlim(-1, 1)
axes.set_ylim(-1, 1)
axes.plot(x_axis, y_axis)
axes.plot(-0.3, -0.5, 0.8, 0.8, marker='o', color='red')

希望对你有帮助。

【讨论】:

这条线可能是垂直的——它只是一条线,而不是函数的图形。【参考方案6】:

我正在检查 ax.axvline 是如何工作的,并且我编写了一个类似于其部分想法的小函数:

import matplotlib.pyplot as plt
import matplotlib.lines as mlines

def newline(p1, p2):
    ax = plt.gca()
    xmin, xmax = ax.get_xbound()

    if(p2[0] == p1[0]):
        xmin = xmax = p1[0]
        ymin, ymax = ax.get_ybound()
    else:
        ymax = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmax-p1[0])
        ymin = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmin-p1[0])

    l = mlines.Line2D([xmin,xmax], [ymin,ymax])
    ax.add_line(l)
    return l

因此,如果您运行以下代码,您将了解它是如何工作的。该线将跨越您的绘图的整个范围(独立于它的大小),并且该线的创建不依赖于轴内的任何数据点,而仅依赖于您需要指定的两个固定点。

import numpy as np
x = np.linspace(0,10)
y = x**2

p1 = [1,20]
p2 = [6,70]

plt.plot(x, y)
newline(p1,p2)
plt.show()

【讨论】:

你定义了yminymax两次,你的代码中可能会被0分开。 除以0?你是什​​么意思?但这是真的,我不需要第一次调用 x.get_ybound() 除以0 -- 如果直线是垂直的。 能否请您准确地说一下您要做什么,而以前的功能无法完成? 完成,现在函数可以画任意线了。我只是为你做检查。

以上是关于如何用 matplotlib 画一条线?的主要内容,如果未能解决你的问题,请参考以下文章

matplotlib画基本图

如何在HTML中画一条线

matplotlib包画基本的图

twoway怎么画一条线

用 CALayer 画一条线

从 UIViewController 画一条线