6

I need to plot a large number of rectangular objects with Matplotlib. Here a simple code with n randomly generated rectangles.

import matplotlib
import matplotlib.pyplot as plt
import random

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
plt.xlim([0, 1001])
plt.ylim([0, 1001])
n=10000
for i in range(0,n):
    x = random.uniform(1, 1000)
    y = random.uniform(1, 1000)
    ax.add_patch(matplotlib.patches.Rectangle((x, y),1,1,))
plt.show()

With n=10000 it takes seconds, but if we increase the number of rectangles to 100K it takes too much time. Any suggestion to improve it, or different approach to have a plot in a reasonable time?

Marco Pavan
  • 143
  • 1
  • 10
  • 1
    I know you are asking for matplotlib, but in your case gnuplot might perform better. I is known, that matplotlib is quite slow compared to gnuplot; http://stackoverflow.com/questions/911655/gnuplot-vs-matplotlib – Moritz Nov 24 '15 at 23:00
  • Thank you for the suggestion, I'm going to try gnuplot. – Marco Pavan Nov 25 '15 at 09:52

1 Answers1

8

Adding all the patches to the plot at once with a PatchCollection produces around a 2-3x speedup with n = 10,000, I'm not sure how well it will scale to larger numbers though:

from matplotlib.collections import PatchCollection
import matplotlib
import matplotlib.pyplot as plt
import random

fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')
plt.xlim([0, 1001])
plt.ylim([0, 1001])
n=10000
patches = []
for i in range(0,n):
    x = random.uniform(1, 1000)
    y = random.uniform(1, 1000)
    patches.append(matplotlib.patches.Rectangle((x, y),1,1,))
ax.add_collection(PatchCollection(patches))
plt.show()
Marius
  • 58,213
  • 16
  • 107
  • 105
  • 2
    Thank you very much. I confirm that your approach produces a 3x speed up. With 100K objects It takes ~40s against ~2m30s. – Marco Pavan Nov 25 '15 at 09:50
  • My `Polygon`s look different if added via a `PatchCollection` than if added to the axes directly. Sadly this makes the plot inferior and unusable. – Michael Currie Jul 17 '23 at 09:09