615 Stimmen

pyplot Punktwolke Markergröße

Im Pyplot-Dokument für Streudiagramme:

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)

Die Markergröße

s: Größe in Punkten^2. Es handelt sich um einen Skalar oder ein Array mit der gleichen Länge wie x und y.

Welche Art von Einheit ist points^2 ? Was bedeutet das? Bedeutet s=100 mittlere 10 pixel x 10 pixel ?

Im Grunde versuche ich, Streudiagramme mit verschiedenen Markergrößen zu erstellen, und ich möchte herausfinden, was die s Nummer bedeuten.

653voto

Dan Punkte 12047

Dies kann eine etwas verwirrende Art sein, die Größe zu definieren, aber im Grunde geben Sie die Bereich der Markierung. Das heißt, um die Breite (oder Höhe) der Markierung zu verdoppeln, müssen Sie die s um den Faktor 4. [weil A = W H => (2W) (2H)=4A]

Es gibt jedoch einen Grund dafür, dass die Größe der Marker auf diese Weise festgelegt wird. Aufgrund der Skalierung der Fläche als Quadrat der Breite scheint eine Verdoppelung der Breite die Größe tatsächlich um mehr als den Faktor 2 zu erhöhen (tatsächlich erhöht sie sich um den Faktor 4). Betrachten Sie dazu die beiden folgenden Beispiele und die daraus resultierende Ausgabe.

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

gibt

enter image description here

Beachten Sie, dass die Größe sehr schnell zunimmt. Wenn wir stattdessen

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

gibt

enter image description here

Nun nimmt die scheinbare Größe der Markierungen auf intuitive Art und Weise ungefähr linear zu.

Was die genaue Bedeutung des Begriffs "Punkt" angeht, so ist er für die Darstellung ziemlich willkürlich, man kann einfach alle Größen um eine Konstante skalieren, bis sie vernünftig aussehen.

Editer : (Als Antwort auf einen Kommentar von @Emma)

Wahrscheinlich habe ich mich missverständlich ausgedrückt. Die Frage bezog sich auf die Verdopplung der Breite eines Kreises. Im ersten Bild ist die Breite jedes Kreises (wenn wir uns von links nach rechts bewegen) doppelt so groß wie die des vorhergehenden Kreises. In ähnlicher Weise hat im zweiten Beispiel jeder Kreis Bereich das Doppelte des letzten Wertes, was einen Exponentialwert zur Basis 2 ergibt.

Im zweiten Beispiel (bei dem wir die Fläche skalieren) scheint die Verdopplung der Fläche den Kreis für das Auge doppelt so groß zu machen. Wenn wir also wollen, dass ein Kreis um einen Faktor von n größer wäre, würden wir die Fläche um einen Faktor n nicht der Radius, so dass die scheinbare Größe linear mit der Fläche skaliert.

bearbeiten um den Kommentar von @TomaszGandor zu visualisieren:

So sieht es bei verschiedenen Funktionen der Markergröße aus:

Exponential, Square, or Linear size

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

349voto

Weil andere Antworten hier behaupten, dass s den Bereich der Markierung bezeichnet, füge ich diese Antwort hinzu, um klarzustellen, dass dies nicht unbedingt der Fall ist.

Größe in Punkten^2

Das Argument s en plt.scatter bezeichnet die markersize**2 . In der Dokumentation heißt es

s Skalar oder array_like, Form (n, ), optional
Größe in Punkten^2. Standardwert ist rcParams['lines.markersize'] ** 2.

Dies kann wörtlich genommen werden. Um einen Marker zu erhalten, der x Punkte groß ist, müssen Sie diese Zahl quadrieren und sie dem s Argument.

Die Beziehung zwischen der Markergröße eines Liniendiagramms und dem Argument der Streuungsgröße ist also quadratisch. Um eine Streuungsmarkierung mit der gleichen Größe wie eine Plotmarkierung der Größe 10 Punkte zu erzeugen, würden Sie also aufrufen scatter( .., s=100) .

enter image description here

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

Verbindung zum "Gebiet"

Warum also sprechen andere Antworten und sogar die Dokumentation von "Gebiet", wenn es um die s Parameter?

Die Einheiten der Punkte**2 sind natürlich Flächeneinheiten.

  • Für den Sonderfall eines quadratischen Markers, marker="s" ist der Bereich der Markierung tatsächlich direkt der Wert der s Parameter.
  • Für einen Kreis ist die Fläche des Kreises area = pi/4*s .
  • Bei anderen Markern besteht möglicherweise nicht einmal ein offensichtlicher Bezug zum Bereich des Markers.

enter image description here

In allen Fällen ist die Fläche der Markierung jedoch proportional zur s Parameter . Dies ist der Grund dafür, dass man es "Gebiet" nennt, obwohl es in den meisten Fällen nicht wirklich eines ist.

Die Angabe der Größe der Streuungsmarker in Form einer Größe, die proportional zur Fläche des Markers ist, ist insofern sinnvoll, als beim Vergleich verschiedener Flecken die Fläche des Markers wahrgenommen wird und nicht seine Seitenlänge oder sein Durchmesser. D.h. eine Verdopplung der zugrundeliegenden Größe sollte die Fläche der Markierung verdoppeln.

enter image description here

Was sind Punkte?

Bisher wurde die Frage, was die Größe einer Streumarke bedeutet, in Punkteinheiten beantwortet. Punkte werden häufig in der Typografie verwendet, wo Schriftarten in Punkten angegeben werden. Auch Linienbreiten werden oft in Punkten angegeben. Die Standardgröße von Punkten in Matplotlib ist 72 Punkte pro Zoll (ppi) - 1 Punkt ist also 1/72 Zoll.

Es könnte nützlich sein, Größen in Pixeln statt in Punkten angeben zu können. Wenn die Abbildung ebenfalls 72 dpi hat, ist ein Punkt ein Pixel. Wenn die dpi der Abbildung anders ist (Matplotlib-Standard ist fig.dpi=100 ),

1 point == fig.dpi/72. pixels

Während die Größe der Streuungsmarkierung in Punkten also für verschiedene Abbildungen in dpi unterschiedlich aussehen würde, könnte man eine 10 x 10 Pixel^2 große Markierung erstellen, die immer die gleiche Anzahl von Pixeln abdeckt:

enter image description here enter image description here enter image description here

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

Wenn Sie an einer Streuung in Dateneinheiten interessiert sind, prüfen Sie diese Antwort .

35voto

zhaoqing Punkte 745

Sie können verwenden Markierungsgröße um die Größe des Kreises in der Plot-Methode anzugeben

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

En aquí

enter image description here

34voto

Joaquin Punkte 441

Es ist die Bereich der Markierung. Ich meine, wenn Sie s1 = 1000 und dann s2 = 4000 ist das Verhältnis zwischen den Radien der einzelnen Kreise: r_s2 = 2 * r_s1 . Siehe die folgende Darstellung:

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

enter image description here

Ich hatte die gleichen Zweifel, als ich den Beitrag sah, also habe ich dieses Beispiel gemacht und dann ein Lineal auf dem Bildschirm benutzt, um die Radien zu messen.

8voto

Ike Punkte 1019

Zu diesem Zweck habe ich zunächst auch versucht, "scatter" zu verwenden. Nach einiger Zeit der Zeitverschwendung habe ich mich für die folgende Lösung entschieden.

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)

enter image description here

Dies beruht auf einer Antwort auf diese Frage

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X