İpython not defterinde bir matplotlib grafiğine rastgele bir çizgi ekleme


119

Hem python / matplotlib'de hem de ipython not defteri aracılığıyla kullanmada oldukça yeniyim. Mevcut bir grafiğe bazı açıklama satırları eklemeye çalışıyorum ve bir grafikteki çizgileri nasıl oluşturacağımı çözemiyorum. Yani, örneğin, aşağıdakileri çizersem:

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

Aşağıdaki grafiği alıyorum:

güzel dağılım grafiği

Peki (70.100) ile (70.250) arasında bir dikey çizgiyi nasıl eklerim? (70,100) ile (90,200) arasındaki çapraz bir çizgiye ne dersiniz?

Benim Line2D()açımdan kafa karışıklığından başka bir şeyle sonuçlanmayan birkaç şey denedim . İçinde Rçizgi segmentleri ekleyen segmentler () fonksiyonunu kullanırdım. Eşdeğeri var matplotlibmı?

Yanıtlar:


185

plotKomutu ilgili verilerle (segmentlerin sınırları) besleyerek istediğiniz çizgileri doğrudan çizebilirsiniz :

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

(tabii ki rengi, çizgi genişliğini, çizgi stilini vb. seçebilirsiniz.)

Örneğinizden:

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

yeni grafik


mükemmel ve eksiksiz resimlerle harika yanıt! Çok çok teşekkürler!
JD Long

2
Küçük bir düzeltme, yukarıdaki kod okunmalıdır x = np.arange(1, 101).
WP McNeill

Bu bir çizgi değil, sadece bir parça çizecektir. Verilen iki noktayı atmak için nasıl çizgi çizileceği sorusu cevapsız kalır.
Alexey

6
@Rmano "_" ile başlayan bir etiket argümanı ekleyerek segmentlerin lejandda dikkate alınmasını önleyebilirsiniz. Ör:plt.plot([70, 70], [100, 250], 'k-', lw=2, label="_not in legend")
gcalmettes

1
Aslında 90hem kullanılır x2ve ve y1potansiyel müşteriler belirsizlik bir sürü. Bunu görüntüleyen herkes için, bunun [70, 90]konumdaki tek bir noktayı ifade etmediğini unutmayın x1,y1. Referans olarak, değerlerin anlamları şunlardır:[x1: 70, x2: 90], [y1: 90, y2: 200]
pookie

61

Yeni gelenler için çok geç değil .

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

Ymin ve ymax kullanarak y'nin aralığını da alır.


1
Axhline ve axvline'ın min / max parametreleri, çizimin kenarına göre çizgileri çizen 0 ile 1 arasındaki skaler değerlerdir. İyi bir araç olmasına rağmen, muhtemelen yazarın açıklama çizgileri çizme sorun ifadesine en iyi çözüm değildir.
binarysubstrate

3
Bu, tüm grafiği kapsayan arka planda bir açıklama satırı eklemek isteyenler için mükemmeldir. Yukarıdaki seçilen çözümü x = 1'de dikey bir çizgi çizmek için kullanırsam, min ve maks y'yi belirtmem gerekir ve ardından grafik bir tamponla otomatik olarak yeniden boyutlandırılır, böylece çizgi tüm arsa boyunca uzanmaz ve bu bir güçlük. Bu daha zariftir ve arsayı yeniden boyutlandırmaz.
Bonnie

40

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

Temel çağrı imzaları şunlardır:

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

2
bu mükemmel. vline()Veya hline()işlevlerini görmemiştim . Çapraz çizgiler ne olacak? Şimdi bana h & v çizgilerini gösterdiğinize göre soruyu çapraz biti eklemek için düzenledim.
JD Long

DataFrameX, y koordinatlarını içeren bir a yapmayı ve bunları grafiğe dökmeyi deneyinstyle='k-'
Austin Richardson

Teşekkürler, bu çok kullanışlı
Alex

6

Matplolib artık OP'nin aradığı gibi 'açıklama satırlarına' izin veriyor. annotate()İşlev, yani çok sayıda bağlantı yollarının formları ve başsız ve tailess oku, basit bir çizgi, bunlardan biri sağlar.

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

Gelen belgeler size ilk argüman olarak boş bir dize ile sadece bir ok çizin söylüyor.

OP'nin örneğinden:

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

Satır içi resim örneği

Gcalmettes'in cevabındaki yaklaşımda olduğu gibi, rengi, çizgi genişliğini, çizgi stilini vb. Seçebilirsiniz.

Burada, kodun bir bölümünde, iki örnek çizgiden birini kırmızı, daha geniş ve% 100 opak değil, daha geniş yapacak bir değişiklik var.

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

Ayrıca ayarlayarak bağlantı çizgisine eğri ekleyebilirsiniz connectionstyle.


1
Sonunda ihtiyacım olan şey buydu. Olay örgüsünün sınırlarının dışına çıkan bir çizgi çizmek istedim .plot()ama yapamaz.
Nick S

5

Kötüye kullanmak yerine plotveya annotatebirçok satır için verimsiz olacak şekilde, şunları kullanabilirsiniz 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 ile çizilen iki çizgi içeren şekil

[l1, l2, ...]Her satırın bir dizi N koordinat olduğu bir satır listesi alır ( N ikiden fazla olabilir).

Standart biçimlendirme anahtar sözcükleri kullanılabilir, tek bir değeri kabul eder, bu durumda değer her satır için geçerlidir veya M dizisi, valuesbu durumda i satırının değeri olur values[i % M].

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.