pyplot dağılım grafiği işaretleyici boyutu


376

Dağılım grafiğinin pyplot belgesinde:

matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None,
                          vmin=None, vmax=None, alpha=None, linewidths=None,
                          faceted=True, verts=None, hold=None, **kwargs)

İşaretleyici boyutu

s: nokta cinsinden boyut ^ 2. Bir skaler veya x ve y ile aynı uzunlukta bir dizidir.

Nasıl bir birim points^2? Bunun anlamı ne? Ne s=100demek 10 pixel x 10 pixel?

Temelde farklı işaretleyici boyutlarına sahip dağılım grafikleri yapmaya çalışıyorum ve sayının ne anlama geldiğini anlamak istiyorum s.


noktaların yazı tipleri için kullanılan aynı birimler olduğundan emin olun.
tacaswell

@tcaswell, yani s=20işaretçi boyutu bir fontsize=20harfin boyutuna eşit mi?
LWZ

hayır, alan 20 punto ^ 2, bir fontsize=20harf 20 punto uzunluğundadır (veya fonttaki referans karakterin uzunluğu 20 puntodur).
tacaswell

23
matplotlib.pyplot.plot()sahip msparametre ( markersize) için bir eşdeğer matplotlib.pyplot.scatter()parametrenin s( size). Sadece bir hatırlatma ..
niekas

@neikas bana öyle değiller, çünkü biri piksel (işaretçi) ve diğeri bu garip kare puan biriminde (boyut). Bu benim için her zaman kafa karıştırıcıydı, ancak miktarın görsel olarak orantılı bir şekilde belirtilmesi için kullanılan dağılım grafiği işaretçisi boyutu ile ilgili olduğuna inanıyorum.
heltonbiker

Yanıtlar:


406

Bu, boyutu tanımlamanın biraz kafa karıştırıcı bir yolu olabilir, ancak temel olarak işaretleyicinin alanını belirtiyorsunuz . Bu, işaretçinin genişliğini (veya yüksekliğini) iki katına çıkarmak için 4 kat artırmanız gerektiği anlamına gelir s. [Çünkü A = W H => (2W) (2H) = 4A]

Bununla birlikte, işaretçilerin boyutunun bu şekilde tanımlanmasının bir nedeni vardır. Alanın genişlik karesi olarak ölçeklendirilmesi nedeniyle, genişliğin iki katına çıkarılması, gerçekte boyutu bir faktör 2'den daha fazla artırıyor gibi görünmektedir (aslında bunu 4 kat arttırır). Bunu görmek için aşağıdaki iki örneği ve ürettikleri çıktıyı göz önünde bulundurun.

# doubling the width of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*4**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()

verir

resim açıklamasını buraya girin

Boyutun nasıl çok hızlı arttığına dikkat edin. Bunun yerine

# doubling the area of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*2**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()

verir

resim açıklamasını buraya girin

Şimdi, belirteçlerin görünen boyutu, sezgisel bir şekilde kabaca doğrusal olarak artmaktadır.

Bir 'noktanın' tam olarak ne olduğuna gelince, çizim amaçları için oldukça keyfidir, makul görünene kadar tüm bedenlerinizi bir sabitle ölçeklendirebilirsiniz.

Bu yardımcı olur umarım!

Düzenleme: (@Emma'dan gelen yoruma yanıt olarak)

Muhtemelen benim için kafa karıştırıcı bir ifade. Soru, bir dairenin genişliğini iki katına çıkarmak istedi, böylece her bir daire için ilk resimde (soldan sağa hareket ettikçe) genişliği bir öncekinin iki katıdır, bu nedenle alan için bu taban 4 ile üsteldir. her dairenin taban 2 ile üs veren sonuncusunun iki katı alanı vardır .

Bununla birlikte, iki katı alanın daireyi göze iki kat daha büyük hale getirdiği ikinci örnek (alanı ölçeklendirdiğimiz yer). Dolayısıyla, bir dairenin ndaha büyük bir faktör olarak görünmesini istiyorsak, alanı nyarıçap değil, bir faktör kadar artıracağız, böylece görünen boyut alanla doğrusal olarak ölçeklenecektir.

Düzenleme @TomaszGandor tarafından yorumunu görselleştirmek için:

İşaretçi boyutunun farklı işlevleri için böyle görünüyor:

Üstel, Kare veya Doğrusal boyut

x = [0,2,4,6,8,10,12,14,16,18]
s_exp = [20*2**n for n in range(len(x))]
s_square = [20*n**2 for n in range(len(x))]
s_linear = [20*n for n in range(len(x))]
plt.scatter(x,[1]*len(x),s=s_exp, label='$s=2^n$', lw=1)
plt.scatter(x,[0]*len(x),s=s_square, label='$s=n^2$')
plt.scatter(x,[-1]*len(x),s=s_linear, label='$s=n$')
plt.ylim(-1.5,1.5)
plt.legend(loc='center left', bbox_to_anchor=(1.1, 0.5), labelspacing=3)
plt.show()

2
Muhtemelen amacınızı yanlış anlıyorum, ancak ikinci örneğinizde s'yi katlanarak artırıyorsunuz (s = [20, 40, 80, 160, 320, 640]) ve bunun bize güzel bir doğrusal görünümlü boyut artışı sağladığını söylüyorsunuz. Boyutu doğrusal olarak arttırmak (ör. S = [20, 40, 60, 80, 100, 120]) bize doğrusal görünümlü sonuç verirse daha anlamlı olmaz mıydı?
Emma

@Emma Sezginiz doğru, benim açımdan zayıf ifadeler (alternatif olarak x ekseni ölçeklendirmesinin zayıf seçimi). Bir yorumda biraz uzun olduğu için bir düzenlemede biraz daha açıkladım.
Dan

1
sŞekil penceresinin boyutuna göre değer değiştirmek mümkün müdür ? Yani, şekil pencerelerini en üst düzeye çıkarırsak, daha büyük boyut işaretlerine sahip olmak isterim.
Sigur

2
Harika bir örnek (sadece gerekli şeyler!). Bu olmamalı 4 ** nve 2 ** nfakat n ** 4ve n ** 2. İle 2 ** nikinci kaptan daire çapı açısından doğrusal ölçekli değildir. Hala çok hızlı gidiyor (üstte o kadar değil).
Tomasz Gandor

1
Daha kısa söylemek gerekirse - ikinci arsa üstel kare kökü gösterir - bu başka bir üstel, sadece biraz daha az dik.
Tomasz Gandor

218

Buradaki diğer cevaplar s, işaretçinin alanını ifade ettiğini iddia ettiğinden , bu cevabı mutlaka böyle olmadığını açıklığa kavuşturmak için ekliyorum.

Puan boyutu ^ 2

Bağımsız değişken solarak plt.scatterbelirtmektedir markersize**2. Belgelerin dediği gibi

s: skaler veya array_like, şekil (n,),
nokta ^ 2 olarak isteğe bağlı boyut. Varsayılan rcParams ['lines.markersize'] ** 2'dir.

Bu tam anlamıyla alınabilir. X punto büyüklüğünde bir işaretleyici elde etmek için, o sayının karesini almanız ve sargümana vermeniz gerekir .

Dolayısıyla, bir çizgi grafiğinin işaret boyutu ile dağılım boyutu argümanı arasındaki ilişki karedir. Bu nedenle, 10 puntoluk bir arsa işaretçisi ile aynı boyutta bir saçılma işareti üretmek için çağırırsınız scatter( .., s=100).

resim açıklamasını buraya girin

import matplotlib.pyplot as plt

fig,ax = plt.subplots()

ax.plot([0],[0], marker="o",  markersize=10)
ax.plot([0.07,0.93],[0,0],    linewidth=10)
ax.scatter([1],[0],           s=100)

ax.plot([0],[1], marker="o",  markersize=22)
ax.plot([0.14,0.86],[1,1],    linewidth=22)
ax.scatter([1],[1],           s=22**2)

plt.show()

"Alan" a bağlantı

Öyleyse neden sparametre söz konusu olduğunda diğer cevaplar ve hatta belgeler "alan" hakkında konuşuyor ?

Tabii ki ** 2 noktalarının birimleri alan birimleridir.

  • Kare işaretleyicinin özel durumu için, işaretleyicinin marker="s"alanı gerçekten de sparametrenin değeridir .
  • Bir daire için, dairenin alanı area = pi/4*s.
  • Diğer işaretçiler için, işaretleyicinin alanı ile açık bir ilişki bile olmayabilir.

resim açıklamasını buraya girin

Ancak her durumda, işaretleyicinin alanı sparametreyle orantılıdır . Çoğu durumda gerçekten olmasa da, buna "alan" deme motivasyonudur.

Dağıtıcı işaretleyicilerin büyüklüğünü, işaretleyicinin alanı ile orantılı olan bir miktar cinsinden belirtmek, işaretleyicinin yan uzunluğu veya çapı yerine farklı yamaları karşılaştırırken algılanan alan olduğu kadar mantıklıdır. Altta yatan miktarı iki katına çıkarmak işaretleyicinin alanını iki katına çıkarmalıdır.

resim açıklamasını buraya girin

Puan nedir?

Şimdiye kadar, bir dağılım işaretleyicisinin boyutunun ne anlama geldiğinin cevabı puan birimleriyle verilmiştir. Noktalar genellikle yazı tiplerinin noktalarda belirtildiği tipografide kullanılır. Ayrıca çizgi genişlikleri genellikle noktalarda belirtilir. Matplotlib'deki noktaların standart boyutu inç başına 72 puntodur (ppi) - 1 nokta dolayısıyla 1/72 inçtir.

Boyutları nokta yerine piksel cinsinden belirtmek yararlı olabilir. Şekil dpi de 72 ise, bir nokta bir pikseldir. Şekil dpi farklıysa (matplotlib varsayılanı fig.dpi=100),

1 point == fig.dpi/72. pixels

Dağılım işaretçisinin noktalardaki boyutu farklı şekil dpi'leri için farklı görünmekle birlikte, her zaman aynı sayıda piksel içerecek şekilde 10 x 10 piksel ^ 2 işaretleyici üretilebilir:

resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin

import matplotlib.pyplot as plt

for dpi in [72,100,144]:

    fig,ax = plt.subplots(figsize=(1.5,2), dpi=dpi)
    ax.set_title("fig.dpi={}".format(dpi))

    ax.set_ylim(-3,3)
    ax.set_xlim(-2,2)

    ax.scatter([0],[1], s=10**2, 
               marker="s", linewidth=0, label="100 points^2")
    ax.scatter([1],[1], s=(10*72./fig.dpi)**2, 
               marker="s", linewidth=0, label="100 pixels^2")

    ax.legend(loc=8,framealpha=1, fontsize=8)

    fig.savefig("fig{}.png".format(dpi), bbox_inches="tight")

plt.show() 

Veri birimlerinde dağılma ile ilgileniyorsanız, bu yanıtı kontrol edin .


Grafiğin gerçek koordinatlarında 0,1 çapını kapsayan bir daire elde etmek için saçılma için verilecek parametrenin nasıl hesaplanacağını merak ederek (bir parsel üzerinde 0.4 ve 0.5 arasındaki boşluğu doldurmak için (0 , 0) - (1,1)?
Anatoly Alekseev

@AnatolyAlekseev Yani tarafından cevap verilmesi gerekir bu soruya.
ImportanceOfBeingErnest

21

Çizim yönteminde dairenin boyutunu belirtmek için işaretçi boyutunu kullanabilirsiniz

import numpy as np
import matplotlib.pyplot as plt

x1 = np.random.randn(20)
x2 = np.random.randn(20)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(x1, 'bo', markersize=20)  # blue circle with size 10 
plt.plot(x2, 'ro', ms=10,)  # ms is just an alias for markersize
plt.show()

Gönderen burada

resim açıklamasını buraya girin


Soru ScatterPlot üzereydi ve matplotlib iki komplo fonksiyonları (farklı parametrelere sahip markersize için arsa ve s için dağılım ). Yani bu cevap geçerli değil.
Dom

3
@Dom'u iptal ettim, çünkü "pyplot arsa işaretçisi boyutu" aradığımda bile bu soru google'da ilk sonuç olarak ortaya çıkıyor, bu yüzden bu cevap yardımcı oluyor.
Przemek D

Ben arsa yöntemi ve saçılma yöntemi plt farklı biliyorum ama her ikisi de 'saçılma arsa' gerçekleştirmek ve markersize ayarlamak, bu yüzden bu cevap başka bir çalışma @Dom
zhaoqing

18

Öyle alan işaretçinin. Eğer varsa demek s1 = 1000ve sonra s2 = 4000, her dairenin çapı arasındaki ilişki aşağıdaki şekildedir: r_s2 = 2 * r_s1. Aşağıdaki taslağa bakınız:

plt.scatter(2, 1, s=4000, c='r')
plt.scatter(2, 1, s=1000 ,c='b')
plt.scatter(2, 1, s=10, c='g')

resim açıklamasını buraya girin

Gönderiyi gördüğümde aynı şüphem vardı, bu yüzden bu örneği yaptım ve daha sonra yarıçapları ölçmek için ekranda bir cetvel kullandım.


Bu en temiz ve en yağsız cevaptır. Teşekkürler
Ayan Mitra

6

Ayrıca başlangıçta bu amaç için 'dağılma' kullanmaya çalıştım. Biraz zaman kaybettikten sonra - aşağıdaki çözüme karar verdim.

import matplotlib.pyplot as plt
input_list = [{'x':100,'y':200,'radius':50, 'color':(0.1,0.2,0.3)}]    
output_list = []   
for point in input_list:
    output_list.append(plt.Circle((point['x'], point['y']), point['radius'], color=point['color'], fill=False))
ax = plt.gca(aspect='equal')
ax.cla()
ax.set_xlim((0, 1000))
ax.set_ylim((0, 1000))
for circle in output_list:    
   ax.add_artist(circle)

resim açıklamasını buraya girin

Bu, bu sorunun cevabına dayanmaktadır


çok yardımcı. Ama neden iki döngü kullanalım?
grabantot

1
@ grabantot hiçbir sebep, sadece içine çok fazla düşünmüyordu.
Ike

2

Dairelerin boyutu, içindeki parametrenin karesine karşılık s=parametergeliyorsa, boyut dizinize eklediğiniz her öğeye bir kare kök atayın, şöyle: s=[1, 1.414, 1.73, 2.0, 2.24]bu değerleri alıp döndürdüğünde, göreceli boyut artışı doğrusal ilerlemeyi döndüren kare ilerlemenin kare kökü.

Ben arsa çıktı alır gibi her biri kare olsaydı: output=[1, 2, 3, 4, 5]. Liste yorumlamasını deneyin:s=[numpy.sqrt(i) for i in s]


1
Olmamalı mı i in output?
Sigur
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.