Подтвердить что ты не робот

Добавление произвольной строки в график matplotlib в записной книжке ipython

Я новичок в 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 я бы просто использовал функцию segment(), которая добавила бы сегменты линии. Существует ли эквивалент в matplotlib?

4b9b3361

Ответ 1

Вы можете напрямую строить линии, которые вы хотите, подавая команду 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

Ответ 2

Еще не поздно для новичков.

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

Он также принимает диапазон y, используя ymin и ymax.

Ответ 3

Использование 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)

Ответ 4

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

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.

Ответ 5

Вместо того, чтобы злоупотреблять plot или annotate, что будет неэффективно для многих строк, вы можете использовать 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()

Figure with two lines plotted via LineCollection

Требуется список строк [l1, l2, ...], где каждая строка представляет собой последовательность из N координат (N может быть больше двух).

Доступны стандартные ключевые слова форматирования, принимающие либо одно значение, в этом случае значение применяется к каждой строке, либо последовательность M values, в этом случае значение для i-й строки равно values[i % M].