In het pyplot-document voor scatterplot:
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)
De markeringsgrootte
en:
grootte in punten^2. Het is een scalair of een array van dezelfde lengte als x en y.
Wat voor soort eenheid is points^2
? Wat betekent het? Betekent s=100
10 pixel x 10 pixel
?
Eigenlijk probeer ik spreidingsdiagrammen te maken met verschillende markeringsgroottes, en ik wil uitzoeken wat het s
-nummer betekent.
Antwoord 1, autoriteit 100%
Dit kan een enigszins verwarrende manier zijn om de grootte te definiëren, maar in feite specificeert u het gebied van de markering. Dit betekent dat om de breedte (of hoogte) van de markering te verdubbelen, je s
met een factor 4 moet vergroten. [omdat A = WH => (2W)(2H)=4A]
Er is echter een reden dat de grootte van markeringen op deze manier wordt gedefinieerd. Vanwege de schaal van het gebied als het kwadraat van de breedte, lijkt een verdubbeling van de breedte de grootte met meer dan een factor 2 te vergroten (in feite wordt deze met een factor 4 vergroot). Bekijk de volgende twee voorbeelden en de output die ze produceren om dit te zien.
# 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()
geeft
Merk op hoe de maat zeer snel toeneemt. Als we in plaats daarvan
# 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()
geeft
Nu neemt de schijnbare grootte van de markeringen op een intuïtieve manier ongeveer lineair toe.
Wat betreft de exacte betekenis van wat een ‘punt’ is, het is vrij willekeurig voor plotdoeleinden, je kunt al je maten gewoon schalen met een constante totdat ze er redelijk uitzien.
Hopelijk helpt dit!
Bewerken: (In reactie op opmerking van @Emma)
Het is waarschijnlijk een verwarrende bewoording van mijn kant. De vraag over het verdubbelen van de breedte van een cirkel, dus in de eerste afbeelding voor elke cirkel (als we van links naar rechts bewegen) is de breedte het dubbele van de vorige, dus voor het gebied is dit een exponentiële met basis 4. Evenzo het tweede voorbeeld elke cirkel heeft een oppervlak het dubbele van de laatste, wat een exponentieel geeft met grondtal 2.
Het is echter het tweede voorbeeld (waar we het gebied schalen) dat verdubbelingsgebied de cirkel twee keer zo groot lijkt te maken voor het oog. Dus als we willen dat een cirkel een factor n
groter lijkt, zouden we de oppervlakte met een factor n
vergroten, niet de straal, dus de schijnbare grootte schaalt lineair met de oppervlakte.
Bewerken om de opmerking van @TomaszGandor te visualiseren:
Zo ziet het eruit voor verschillende functies van de markeringsgrootte:
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()
Antwoord 2, autoriteit 54%
Omdat andere antwoorden hier beweren dat s
het gebied van de markering aangeeft, voeg ik dit antwoord toe om duidelijk te maken dat dit niet noodzakelijk het geval is.
Grootte in punten^2
Het argument s
in plt.scatter
geeft de markersize**2
aan. Zoals de documentatie zegt
s
: scalair of array_like, vorm (n, ), optioneel
grootte in punten^2. Standaard is rcParams[‘lines.markerssize’] ** 2.
Dit kan letterlijk worden genomen. Om een markering te krijgen die x punten groot is, moet je dat getal kwadrateren en aan het argument s
geven.
Dus de relatie tussen de markeringsgrootte van een lijnplot en het argument voor de spreidingsgrootte is het kwadraat. Om een spreidingsmarkering te produceren van dezelfde grootte als een plotmarkering van 10 punten, roep je daarom scatter( .., s=100)
aan.
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()
Verbinding met “gebied”
Dus waarom spreken andere antwoorden en zelfs de documentatie over “gebied” als het gaat om de parameter s
?
Natuurlijk zijn de eenheden van punten**2 oppervlakte-eenheden.
- Voor het speciale geval van een vierkante markering,
marker="s"
, is het gebied van de markering inderdaad direct de waarde van de parameters
. - Voor een cirkel is de oppervlakte van de cirkel
area = pi/4*s
. - Voor andere markeringen is er misschien niet eens een duidelijke relatie met het gebied van de markering.
In alle gevallen is het gebied van de markering echter evenredig met de s
parameter. Dit is de motivatie om het “gebied” te noemen, hoewel dat in de meeste gevallen niet echt is.
Het specificeren van de grootte van de verstrooiingsmarkeringen in termen van een hoeveelheid die evenredig is met het gebied van de markering is in zoverre logisch, aangezien het het gebied van de markering is dat wordt waargenomen bij het vergelijken van verschillende patches in plaats van de lengte van de zijkant of diameter. D.w.z. verdubbeling van de onderliggende hoeveelheid zou de oppervlakte van de marker moeten verdubbelen.
Wat zijn punten?
Tot nu toe wordt het antwoord op wat de grootte van een spreidingsmarkering betekent, gegeven in eenheden van punten. Punten worden vaak gebruikt in typografie, waar lettertypen in punten worden gespecificeerd. Ook lijnbreedten worden vaak in punten aangegeven. De standaardgrootte van punten in matplotlib is 72 punten per inch (ppi) – 1 punt is dus 1/72 inch.
Het kan handig zijn om de grootte in pixels te kunnen specificeren in plaats van in punten. Als het cijfer dpi ook 72 is, is één punt één pixel. Als het cijfer dpi anders is (de standaardwaarde van matplotlib is fig.dpi=100
),
1 point == fig.dpi/72. pixels
Hoewel de grootte van de spreidingsmarkering in punten er dus anders uitziet voor verschillende dpi-cijfers, zou men een markering van 10 bij 10 pixels^2 kunnen produceren, die altijd hetzelfde aantal pixels bedekt:
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()
Als je geïnteresseerd bent in een spreiding in data-eenheden, bekijk dan dit antwoord.
Antwoord 3, autoriteit 6%
U kunt markersize gebruiken om de grootte van de cirkel in de plotmethode op te geven
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()
Van hier
Antwoord 4, autoriteit 5%
Dit is het gebied van de markering. Ik bedoel, als je s1 = 1000
en dan s2 = 4000
hebt, is de relatie tussen de straal van elke cirkel: r_s2 = 2 * r_s1
. Zie de volgende plot:
plt.scatter(2, 1, s=4000, c='r')
plt.scatter(2, 1, s=1000 ,c='b')
plt.scatter(2, 1, s=10, c='g')
Ik had dezelfde twijfel toen ik de post zag, dus ik deed dit voorbeeld en vervolgens gebruikte ik een liniaal op het scherm om de stralen te meten.
Antwoord 5, autoriteit 2%
Ik heb in eerste instantie ook geprobeerd om ‘scatter’ voor dit doel te gebruiken. Na nogal wat tijdverspilling – kwam ik tot de volgende oplossing.
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)
Dit is gebaseerd op een antwoord op deze vraag
Antwoord 6
Als de grootte van de cirkels overeenkomt met het kwadraat van de parameter in s=parameter
, wijs dan een vierkantswortel toe aan elk element dat je toevoegt aan je groottearray, als volgt: s=[1, 1.414, 1.73, 2.0, 2.24]
zodat wanneer deze waarden worden genomen en geretourneerd, hun relatieve groottetoename de vierkantswortel zal zijn van de kwadratische progressie, die een lineaire progressie retourneert.
Als ik ze allemaal zou kwadrateren als het wordt uitgevoerd naar de plot: output=[1, 2, 3, 4, 5]
. Probeer lijstinterpretatie: s=[numpy.sqrt(i) for i in s]