La chiave qui è quello di utilizzare un Collection
. Nel tuo caso, vuoi fare un PatchCollection
.
Matplotlib ottimizza il disegno di molti artisti simili mediante l'utilizzo di raccolte. È considerevolmente più veloce del disegnare ognuno individualmente. Inoltre, la trama non conterrà migliaia di singoli artisti, solo una collezione. Questo accelera molte altre operazioni varie che devono operare su ciascun artista ogni volta che viene tracciata la trama.
scatter
in realtà è molto più veloce del tuo attuale approccio, in quanto aggiungerà una raccolta invece di artisti separati. Tuttavia, disegna anche indicatori con una dimensione che non è in coordinate di dati.
Per aggirare il problema, è possibile utilizzare lo stesso approccio scatter
ma creare la raccolta manualmente.
Per fare un esempio:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.collections
num = 5000
sizes = 0.2 * np.random.random(num)
xy = 50 * np.random.random((num, 2))
# Note that the patches won't be added to the axes, instead a collection will
patches = [plt.Circle(center, size) for center, size in zip(xy, sizes)]
fig, ax = plt.subplots()
coll = matplotlib.collections.PatchCollection(patches, facecolors='black')
ax.add_collection(coll)
ax.margins(0.01)
plt.show()
Ciò rende piuttosto agevolmente per me.Solo per dimostrare che i cerchi sono in coordinate di dati, notare cosa succede se ingrandire un rettangolo stretto (nota: ciò presuppone che l'aspetto della trama è impostata auto
):
Se sei veramente concentrato sulla velocità, puoi usare uno EllipseCollection
come suggerito da @tcaswell.
Un EllipseCollection
farà solo una percorso, ma scalerà e tradurlo in fase di sorteggio per essere nei luoghi/formati specificati.
Lo svantaggio è che mentre la dimensione può essere in coordinate di dati, il cerchio sarà sempre un cerchio, anche se il rapporto di aspetto del grafico non è 1. (cioè i cerchi non si allungheranno come fanno in la figura sopra).
Il vantaggio è che è veloce.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.collections
num = 5000
sizes = 0.4 * np.random.random(num)
xy = 50 * np.random.random((num, 2))
fig, ax = plt.subplots()
coll = matplotlib.collections.EllipseCollection(sizes, sizes,
np.zeros_like(sizes),
offsets=xy, units='x',
transOffset=ax.transData,
**kwargs)
ax.add_collection(coll)
ax.margins(0.01)
plt.show()
notare la differenza come abbiamo ingrandire una regione simile alla seconda cifra. I cerchi diventano più grandi (la dimensione è in coordinate di dati), ma rimangono cerchi invece di allungarsi. Non sono una rappresentazione accurata di un cerchio nello spazio "dati".
Per dare un'idea della differenza di tempo, ecco il tempo per creare e disegnare una figura con gli stessi 5000 cerchi con ciascuno dei tre metodi:
In [5]: %timeit time_plotting(circles)
1 loops, best of 3: 3.84 s per loop
In [6]: %timeit time_plotting(patch_collection)
1 loops, best of 3: 1.37 s per loop
In [7]: %timeit time_plotting(ellipse_collection)
1 loops, best of 3: 228 ms per loop
si desidera utilizzare un 'EllipseCollection' potrebbe fare ciò che vuoi http://matplotlib.org/examples/pylab_examples/ellipse_collection.html – tacaswell