ipython 노트북의 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단순히 세그먼트를 사용하는 것이 () 함수 선 세그먼트를 추가 할 수있다. 에 상응하는 것이 matplotlib있습니까?

답변:


185

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모두 사용 된다는 사실 은 많은 모호성을 유발합니다. 이것을 보는 사람 은 location의 단일 지점을 의미하지 않습니다 . 참고로 값의 의미는 다음과 같습니다.x2y1[70, 90]x1,y1[x1: 70, x2: 90], [y1: 90, y2: 200]
pookie

61

신규 이민자 에게는 너무 늦지 않았습니다 .

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

ymin 및 ymax를 사용하여 y의 범위도 사용합니다.


1
axhline 및 axvline의 최소 / 최대 매개 변수는 플롯의 모서리를 기준으로 선을 그리는 0과 1 사이의 스칼라 값입니다. 좋은 도구이지만 주석 선을 그리는 저자의 문제 진술에 대한 최선의 해결책은 아닐 것입니다.
binarysubstrate 2014

3
전체 그래프에 걸쳐 배경에 주석 선을 추가하려는 경우에 적합합니다. 위에서 선택한 솔루션을 사용하여 x = 1에서 수직선을 그리면 최소 및 최대 y를 지정해야합니다. 그러면 플롯이 버퍼를 사용하여 자동으로 크기가 조정되어 선이 전체 플롯에 걸쳐 늘어나지 않습니다. 그것은 번거 롭습니다. 이것은 더 우아하고 플롯의 크기를 조정하지 않습니다.
Bonnie

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 Long

DataFramex, y 좌표를 포함하고 다음과 같이 플로팅 해보십시오style='k-'
Austin Richardson

매우 편리합니다, 당신을 감사
알렉스

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()수 없습니다.
Nick S

5

많은 라인에서 비효율적 인 plotor를 남용하는 대신 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()

LineCollection을 통해 그려진 두 줄이있는 그림

라인 목록을 가져옵니다. [l1, l2, ...]여기서 각 라인은 N 좌표 ( N 은 두 개 이상일 수 있음).

표준 서식 지정 키워드를 사용할 수 있으며 단일 값 (값이 모든 줄에 적용되는 경우) 또는 M 시퀀스 ( values이 경우 i 번째 줄 의 값이)를 허용합니다 values[i % M].

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.