在ipython Notebook中向matplotlib图添加任意行


119

我对python / matplotlib以及通过ipython笔记本使用它都比较陌生。我正在尝试向现有图形添加一些注释线,但无法弄清楚如何在图形上呈现这些线。因此,例如,如果我绘制以下内容:

import numpy as np
np.random.seed(5)
x = arange(1, 101)
y = 20 + 3 * x + np.random.normal(0, 60, 100)
p =  plot(x, y, "o")

我得到以下图:

美丽的散点图

那么,如何添加一条从(70,100)到(70,250)的垂直线?从(70,100)到(90,200)的对角线呢?

我尝试了几件事,Line2D()但除了困惑之外,没有其他事情。在这里,R我将简单地使用segments()函数添加线段。有对应的matplotlib吗?

Answers:


184

您可以通过向plot命令提供相应的数据(线段的边界)来直接绘制所需的线:

plot([x1, x2], [y1, y2], color='k', linestyle='-', linewidth=2)

(当然,您可以选择颜色,线宽,线型等)

从您的示例:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(5)
x = np.arange(1, 101)
y = 20 + 3 * x + np.random.normal(0, 60, 100)
plt.plot(x, y, "o")


# draw vertical line from (70,100) to (70, 250)
plt.plot([70, 70], [100, 250], 'k-', lw=2)

# draw diagonal line from (70, 90) to (90, 200)
plt.plot([70, 90], [90, 200], 'k-')

plt.show()

新图表


精美完整的插图,很好的答案!非常感谢!
京东(JD Long)

2
进行较小的更正,上面的代码应为x = np.arange(1, 101)
WP McNeill

这不会画一条线,而只会画一条线。如何画一条线向两个给定的点扔的问题仍然没有答案。
Alexey

6
@Rmano您可以通过添加以“ _”开头的标签参数来避免在图例中考虑分段。例如:plt.plot([70, 70], [100, 250], 'k-', lw=2, label="_not in legend")
gcalmettes

1
90用作x2和并y1导致许多歧义的事实。对于任何查看此内容的人,请注意,[70, 90]它并不指向location上的单个点x1,y1。作为参考,以下是这些值的含义:[x1: 70, x2: 90], [y1: 90, y2: 200]
pookie

61

对于新来者来说还不算太晚。

plt.axvline(x, color='r')

它也使用ymin和ymax取y的范围。


1
axhline和axvline的min / max参数是0到1之间的标量值,该标量值相对于图的边缘绘制线。尽管是一个很好的工具,但它可能不是解决作者注释标注线问题的最佳解决方案。
binarysubstrate 2014年

3
这是想要在背景中添加跨越整个图形的注释行的理想选择。如果使用上面选择的解决方案在x = 1处绘制一条垂直线,则必须指定最小值和最大值y,然后使用缓冲区自动调整图的大小,因此该线不会延伸到整个图,并且这很麻烦。这更加优雅,不会调整情节的大小。
邦妮

40

使用vlines

import numpy as np
np.random.seed(5)
x = arange(1, 101)
y = 20 + 3 * x + np.random.normal(0, 60, 100)
p =  plot(x, y, "o")
vlines(70,100,250)

基本的呼叫签名是:

vlines(x, ymin, ymax)
hlines(y, xmin, xmax)

2
太好了 我没有看到vline()hline()功能。那对角线呢?现在,您已经向我展示了h&v线,因此我编辑了问题以添加对角线位。
京东(JD)

尝试制作一个DataFrame包含x,y坐标的图形,并使用style='k-'
奥斯汀·理查森

谢谢您,这非常方便
Alex

6

Matplolib现在允许OP寻求“注释行”。该annotate()功能允许多种形式的连接路径,无头箭和无尾箭就是其中之一。

ax.annotate("",
            xy=(0.2, 0.2), xycoords='data',
            xytext=(0.8, 0.8), textcoords='data',
            arrowprops=dict(arrowstyle="-",
                      connectionstyle="arc3, rad=0"),
            )

它在文档中说您只能绘制带有空字符串的箭头作为第一个参数。

从OP的示例中:

%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(5)
x = np.arange(1, 101)
y = 20 + 3 * x + np.random.normal(0, 60, 100)
plt.plot(x, y, "o")


# draw vertical line from (70,100) to (70, 250)
plt.annotate("",
              xy=(70, 100), xycoords='data',
              xytext=(70, 250), textcoords='data',
              arrowprops=dict(arrowstyle="-",
                              connectionstyle="arc3,rad=0."), 
              )

# draw diagonal line from (70, 90) to (90, 200)
plt.annotate("",
              xy=(70, 90), xycoords='data',
              xytext=(90, 200), textcoords='data',
              arrowprops=dict(arrowstyle="-",
                              connectionstyle="arc3,rad=0."), 
              )

plt.show()

内嵌图片示例

就像gcalmettes答案中的方法一样,您可以选择颜色,线宽,线型等。

这是对部分代码的更改,将使两个示例行之一变为红色,更宽且并非100%不透明。

# draw vertical line from (70,100) to (70, 250)
plt.annotate("",
              xy=(70, 100), xycoords='data',
              xytext=(70, 250), textcoords='data',
              arrowprops=dict(arrowstyle="-",
                              edgecolor = "red",
                              linewidth=5,
                              alpha=0.65,
                              connectionstyle="arc3,rad=0."), 
              )

您还可以通过调整来将曲线添加到连接线connectionstyle


1
这就是我最终需要的。我想画一条超出情节边界的线,这.plot()是行不通的。
尼克S

5

而不是滥用plotannotate,这将是低效的多条线路,则可以使用matplotlib.collections.LineCollection

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection

np.random.seed(5)
x = np.arange(1, 101)
y = 20 + 3 * x + np.random.normal(0, 60, 100)
plt.plot(x, y, "o")

# Takes list of lines, where each line is a sequence of coordinates
l1 = [(70, 100), (70, 250)]
l2 = [(70, 90), (90, 200)]
lc = LineCollection([l1, l2], color=["k","blue"], lw=2)

plt.gca().add_collection(lc)

plt.show()

通过LineCollection绘制两条线的图

它采用行列表[l1, l2, ...],其中每行是N个坐标的序列(N可以大于两个)。

标准格式设置关键字可用,可以接受一个值(在这种情况下该值适用于每一行),也可以接受一个序列M values(在这种情况下,第i行的值是)values[i % M]

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.