Whether exploring data in interactive mode or programmatically saving lots of plots, rendering performance can be a challenging bottleneck in your pipeline. Matplotlib provides multiple ways to greatly reduce rendering time at the cost of a slight change (to a settable tolerance) in your plot's appearance. The methods available to reduce rendering time depend on the type of plot that is being created.
Line segment simplification#
For plots that have line segments (e.g. typical line plots, outlines
of polygons, etc.), rendering performance can be controlled by
can be defined e.g. in the
matplotlibrc file (see
Customizing Matplotlib with style sheets and rcParams for more information about
True) is a Boolean
indicating whether or not line segments are simplified at all.
0.111111111111) controls how much line segments are simplified;
higher thresholds result in quicker rendering.
The following script will first display the data without any simplification, and then display the same data with simplification. Try interacting with both of them:
import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl # Setup, and create the data to plot y = np.random.rand(100000) y[50000:] *= 2 y[np.geomspace(10, 50000, 400).astype(int)] = -1 mpl.rcParams['path.simplify'] = True mpl.rcParams['path.simplify_threshold'] = 0.0 plt.plot(y) plt.show() mpl.rcParams['path.simplify_threshold'] = 1.0 plt.plot(y) plt.show()
Matplotlib currently defaults to a conservative simplification
1/9. To change default settings to use a different
value, change the
matplotlibrc file. Alternatively, users
can create a new style for interactive plotting (with maximal
simplification) and another style for publication quality plotting
(with minimal simplification) and activate them as necessary. See
Customizing Matplotlib with style sheets and rcParams for instructions on
how to perform these actions.
The simplification works by iteratively merging line segments
into a single vector until the next line segment's perpendicular
distance to the vector (measured in display-coordinate space)
is greater than the
Changes related to how line segments are simplified were made in version 2.1. Rendering time will still be improved by these parameters prior to 2.1, but rendering time for some kinds of data will be vastly improved in versions 2.1 and greater.
Markers can also be simplified, albeit less robustly than line
segments. Marker subsampling is only available to
markevery property). Wherever
parameters are passed through, such as
markevery parameter can be used:
plt.plot(x, y, markevery=10)
markevery argument allows for naive subsampling, or an
attempt at evenly spaced (along the x axis) sampling. See the
for more information.
Splitting lines into smaller chunks#
If you are using the Agg backend (see What is a backend?),
then you can make use of
This allows users to specify a chunk size, and any lines with
greater than that many vertices will be split into multiple
lines, each of which has no more than
many vertices. (Unless
agg.path.chunksize is zero, in
which case there is no chunking.) For some kind of data,
chunking the line up into reasonable sizes can greatly
decrease rendering time.
The following script will first display the data without any chunk size restriction, and then display the same data with a chunk size of 10,000. The difference can best be seen when the figures are large, try maximizing the GUI and then interacting with them:
import numpy as np import matplotlib.pyplot as plt import matplotlib as mpl mpl.rcParams['path.simplify_threshold'] = 1.0 # Setup, and create the data to plot y = np.random.rand(100000) y[50000:] *= 2 y[np.geomspace(10, 50000, 400).astype(int)] = -1 mpl.rcParams['path.simplify'] = True mpl.rcParams['agg.path.chunksize'] = 0 plt.plot(y) plt.show() mpl.rcParams['agg.path.chunksize'] = 10000 plt.plot(y) plt.show()
The default legend behavior for axes attempts to find the location
that covers the fewest data points (
loc='best'). This can be a
very expensive computation if there are lots of data points. In
this case, you may want to provide a specific location.
Using the fast style#
The fast style can be used to automatically set simplification and chunking parameters to reasonable settings to speed up plotting large amounts of data. The following code runs it:
import matplotlib.style as mplstyle mplstyle.use('fast')
It is very lightweight, so it works well with other styles. Be sure the fast style is applied last so that other styles do not overwrite the settings:
mplstyle.use(['dark_background', 'ggplot', 'fast'])