向 ipython 笔记本中的 matplotlib 图添加任意一行

我对 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")

我得到如下图表:

beautiful scatter plot

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

我已经尝试了一些事情与 Line2D()导致什么也没有,但我的部分混乱。在 R中,我会简单地使用切片()函数来添加线段。在 matplotlib中有一个等价物吗?

376862 次浏览

使用 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)

您可以通过向 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()

new chart

现在做 新来的还不晚。

plt.axvline(x, color='r') # vertical
plt.axhline(x, color='r') # horizontal

它也采用 y的范围,使用 yminymax

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"),
)

文件中,它说你只能用一个空字符串作为第一个参数来画一个箭头。

以观察所为例:

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

Example inline image

正如在 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向连接线添加曲线。

你可以使用 matplotlib.collections.LineCollection,而不是滥用 plotannotate,因为它们对于很多行来说都是低效的:

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

Figure with two lines plotted via LineCollection

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

标准格式化关键字是可用的,接受单个值(在这种情况下,该值应用于每一行)或 M values序列(在这种情况下,行的值为 values[i % M])。