dimensione del marker del grafico a dispersione pyplot


376

Nel documento pyplot per diagramma a dispersione:

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)

La dimensione del marker

s: dimensione in punti ^ 2. È uno scalare o un array della stessa lunghezza di xey.

Che tipo di unità è points^2? Cosa significa? Non s=100significa 10 pixel x 10 pixel?

Fondamentalmente sto cercando di creare grafici a dispersione con dimensioni dei marker diverse e voglio capire cosa significa il snumero.


abbastanza sicuro che i punti siano le stesse unità usate per i caratteri.
Tacaswell,

@tcaswell, vuoi dire che s=20la dimensione del marker è uguale a quella di una fontsize=20lettera?
LWZ,

no, l'area sarà di 20 punti ^ 2, una fontsize=20lettera è alta 20 punti (o qualunque sia il carattere di riferimento nel carattere è alto 20 punti).
Tacaswell,

23
matplotlib.pyplot.plot()ha msparametro ( markersize) un equivalente per matplotlib.pyplot.scatter()parametro s( size). Solo un promemoria ..
Niekas,

@neikas mi sembra che non lo siano, dato che uno è in pixel (dimensione del segno) e l'altro è in questa strana unità di punti quadrati (dimensione). Questo mi ha sempre confuso, ma credo che abbia a che fare con la dimensione del marker scatterplot utilizzata per indicare la quantità in modo visivamente proporzionale.
heltonbiker,

Risposte:


406

Questo può essere un modo un po 'confuso per definire la dimensione, ma sostanzialmente stai specificando l' area del marcatore. Ciò significa che per raddoppiare la larghezza (o l'altezza) del marker è necessario aumentare sdi un fattore 4. [perché A = W H => (2W) (2H) = 4A]

C'è una ragione, tuttavia, che la dimensione dei marker è definita in questo modo. A causa del ridimensionamento dell'area come il quadrato della larghezza, il raddoppio della larghezza sembra effettivamente aumentare la dimensione di più di un fattore 2 (in realtà la aumenta di un fattore 4). Per vederlo, considera i seguenti due esempi e l'output che producono.

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

inserisci qui la descrizione dell'immagine

Notare come le dimensioni aumentano molto rapidamente. Se invece abbiamo

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

inserisci qui la descrizione dell'immagine

Ora la dimensione apparente dei marker aumenta approssimativamente in modo lineare in modo intuitivo.

Per quanto riguarda il significato esatto di cosa sia un "punto", è abbastanza arbitrario ai fini della stampa, puoi semplicemente ridimensionare tutte le dimensioni di una costante fino a quando sembrano ragionevoli.

Spero che sia di aiuto!

Modifica: (in risposta al commento di @Emma)

Probabilmente è una formulazione confusa da parte mia. La domanda si è posta sul raddoppio della larghezza di un cerchio, quindi nella prima immagine per ogni cerchio (mentre ci spostiamo da sinistra a destra) la sua larghezza è doppia rispetto alla precedente, quindi per l'area questo è un esponenziale con base 4. Allo stesso modo il secondo esempio ogni cerchio ha un'area doppia rispetto all'ultimo che fornisce un esponenziale con base 2.

Tuttavia è il secondo esempio (dove stiamo ridimensionando l'area) che l'area del raddoppio sembra rendere il cerchio due volte più grande dell'occhio. Pertanto, se vogliamo che un cerchio appaia un fattore npiù grande, aumenteremmo l'area di un fattore e nnon del raggio, quindi la dimensione apparente si ridimensiona linearmente con l'area.

Modifica per visualizzare il commento di @TomaszGandor:

Ecco come si presenta per diverse funzioni della dimensione del marker:

Dimensioni esponenziali, quadrate o lineari

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
Probabilmente sto fraintendendo il tuo punto, ma nel tuo secondo esempio stai aumentando s in modo esponenziale (s = [20, 40, 80, 160, 320, 640]) e dicendo che ciò ci dà un piacevole aumento delle dimensioni dall'aspetto lineare. Non avrebbe più senso se aumentare le dimensioni in modo lineare (es. S = [20, 40, 60, 80, 100, 120]) ci da un risultato lineare?
Emma,

@Emma La tua intuizione è giusta, è una povera formulazione da parte mia (in alternativa scarsa scelta del ridimensionamento dell'asse x). Ho spiegato un po 'di più in una modifica perché era troppo lungo per un commento.
Dan,

1
È possibile modificare il svalore in base alle dimensioni della finestra della figura? Voglio dire, se massimizziamo le finestre delle figure, vorrei avere segni di dimensioni maggiori.
Sigur,

2
Ottimo esempio (solo le cose necessarie!). Questo non dovrebbe essere 4 ** ne 2 ** n, ma n ** 4e n ** 2. Con 2 ** nil secondo grafico non si ridimensiona linearmente in termini di diametro del cerchio. Va ancora troppo veloce (ma non troppo sopra).
Tomasz Gandor,

1
Per dirla in breve - la seconda trama mostra la radice quadrata dell'esponenziale - che è un altro esponenziale, solo un po 'meno ripido.
Tomasz Gandor,

218

Poiché altre risposte qui affermano che sindica l'area del marcatore, sto aggiungendo questa risposta per chiarire che non è necessariamente così.

Dimensione in punti ^ 2

L'argomento sin plt.scatterindica il markersize**2. Come dice la documentazione

s: scalare o array_like, forma (n,),
dimensione opzionale in punti ^ 2. L'impostazione predefinita è rcParams ['lines.markersize'] ** 2.

Questo può essere preso alla lettera. Per ottenere un marcatore che è x punti grandi, è necessario quadrare quel numero e assegnarlo sall'argomento.

Quindi la relazione tra la dimensione marcata di un grafico a linee e l'argomento della dimensione della dispersione è il quadrato. Al fine di produrre un marcatore a dispersione della stessa dimensione di un marcatore a trama di dimensione 10 punti che chiamereste scatter( .., s=100).

inserisci qui la descrizione dell'immagine

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

Collegamento a "area"

Quindi perché altre risposte e persino la documentazione parlano di "area" quando si tratta del sparametro?

Naturalmente le unità di punti ** 2 sono unità di area.

  • Per il caso speciale di un marcatore quadrato marker="s", l'area del marcatore è effettivamente direttamente il valore del sparametro.
  • Per un cerchio, l'area del cerchio è area = pi/4*s.
  • Per altri marcatori potrebbe non esserci nemmeno una relazione evidente con l'area del marcatore.

inserisci qui la descrizione dell'immagine

In tutti i casi, tuttavia, l'area del marker è proporzionale al sparametro . Questa è la motivazione per chiamarla "area" anche se nella maggior parte dei casi non lo è.

Specificare la dimensione dei marker di dispersione in termini di una certa quantità che è proporzionale all'area del marker ha senso finora in quanto è l'area del marker che viene percepita quando si confrontano patch diverse anziché la sua lunghezza o diametro laterale. Vale a dire il raddoppio della quantità sottostante dovrebbe raddoppiare l'area del marcatore.

inserisci qui la descrizione dell'immagine

Quali sono i punti?

Finora la risposta a ciò che significa la dimensione di un marker scatter è data in unità di punti. I punti sono spesso usati in tipografia, dove i caratteri sono specificati in punti. Anche le larghezze di linea sono spesso specificate in punti. La dimensione standard dei punti in matplotlib è 72 punti per pollice (ppi) - 1 punto è quindi 1/72 pollici.

Potrebbe essere utile poter specificare le dimensioni in pixel anziché in punti. Se anche la cifra in dpi è 72, un punto è un pixel. Se il valore dpi è diverso (impostazione predefinita matplotlib fig.dpi=100),

1 point == fig.dpi/72. pixels

Mentre le dimensioni del marcatore a dispersione in punti apparirebbero quindi diverse per i diversi valori dpi, si potrebbe produrre un marcatore 10 per 10 pixel ^ 2, che avrebbe sempre lo stesso numero di pixel coperti:

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

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

Se sei interessato a una dispersione in unità di dati, controlla questa risposta .


Chiedendosi come si calcola quale parametro dare alla dispersione per ottenere un cerchio che copre il diametro di, diciamo, 0.1 in coordinate reali del diagramma (in modo da riempire il divario tra diciamo 0.4 e 0.5 su un diagramma da (0 , Da 0) a (1,1)?
Anatoly Alekseev il

@AnatolyAlekseev A questa domanda dovrebbe rispondere .
ImportanceOfBeingErnest

21

È possibile utilizzare Markersize per specificare la dimensione del cerchio nel metodo grafico

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

Da qui

inserisci qui la descrizione dell'immagine


La domanda riguardava scatterplot, e in matplotlib le due funzioni di tracciamento hanno parametri diversi ( marcatura per trama , e s per dispersione ). Quindi questa risposta non si applica.
Dom

3
@Dom Ho effettuato l'upgrade, perché questa domanda viene visualizzata come primo risultato in google anche quando cerco "dimensioni dell'indicatore di trama pyplot", quindi questa risposta aiuta.
Przemek D,

So che il metodo di trama e il metodo di dispersione sono diversi nel plt ma entrambi possono realizzare il 'diagramma di dispersione' e regolare la dimensione del segno, quindi questa risposta è solo un'altra soluzione se usi il metodo di trama @Dom
zhaoqing

18

È l' area del marcatore. Voglio dire, se si dispone s1 = 1000e poi s2 = 4000, il rapporto fra il raggio di ogni cerchio è: r_s2 = 2 * r_s1. Vedi la seguente trama:

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

inserisci qui la descrizione dell'immagine

Avevo lo stesso dubbio quando ho visto il post, quindi ho fatto questo esempio quindi ho usato un righello sullo schermo per misurare i raggi.


Questa è la risposta più pulita e senza grassi. Grazie
Ayan Mitra il

6

Ho anche tentato di usare inizialmente 'scatter' per questo scopo. Dopo un bel po 'di tempo sprecato, ho optato per la seguente soluzione.

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)

inserisci qui la descrizione dell'immagine

Questo si basa su una risposta a questa domanda


molto utile. Ma perché usare due loop?
Grabantot,

1
@grabantot nessun motivo, solo non ci ho pensato molto.
Ike,

2

Se la dimensione dei cerchi corrisponde al quadrato del parametro in s=parameter, quindi assegna una radice quadrata a ciascun elemento che aggiungi alla tua matrice di dimensioni, in questo modo: in modo s=[1, 1.414, 1.73, 2.0, 2.24]tale che quando prende questi valori e li restituisce, il loro aumento relativo delle dimensioni sarà la radice quadrata della progressione quadrata, che restituisce una progressione lineare.

Se dovessi quadrare ciascuno, come si arriva uscita del terreno: output=[1, 2, 3, 4, 5]. Prova l'interpretazione dell'elenco:s=[numpy.sqrt(i) for i in s]


1
Non dovrebbe essere i in output?
Sigur,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.