## Problem statement:

You need to plot a large collection of line segments in Matplotlib.

## Solution:

If you try to plot a collection of  lines segments in Matplotlib using sequential calls to plot, it can take a lot of time to generate the graph. There are two ways to speed up the plotting. The first is to use pythons extended call syntax and pass multiple lines segments at a time. The other is to create a single list of points, where the line segments are separated by ‘None’ values. The extended call method yields a minor improvement in performance. Forming a single list of line segments separated by ‘None’ results in a significant time savings. For the test cases below, using extended call syntax decreased drawing time by about 10% and using a single list separated by ‘None’ decreased drawing time by more than 99%.

Execution time for sequential plotting = 11.083103 sec
Execution time for extended call plotting = 10.245883 sec
Execution time when using None = = 0.027801 sec

## Sample Code:

import time
import sys
import matplotlib.pyplot as pp
import random

if sys.platform == "win32":
# On Windows, the best timer is time.clock()
default_timer = time.clock
else:
# On most other platforms the best timer is time.time()
default_timer = time.time

# generate ends for the line segments
xpairs = []
ypairs = []
for i in range(1000):
xends = [random.random(), random.random()]
yends = [random.random(), random.random()]
xpairs.append(xends)
ypairs.append(yends)

############################
# time sequential call to matplotlib
pp.figure()
pp.subplot(1,3,1)

t0 = default_timer()
for xends,yends in zip(xpairs,ypairs):
pp.plot(xends,yends,'b-',alpha=0.1)
t1 = default_timer()

pp.title('Sequential Plotting')

print 'Execution time for sequential plotting = %f sec' % (t1-t0)

############################
# build argument list
call_list = []
for xends,yends in zip(xpairs,ypairs):
call_list.append(xends)
call_list.append(yends)
call_list.append('-b')

############################
# time single call to matplotlib
pp.subplot(1,3,2)

t0 = default_timer()
pp.plot(*call_list,alpha=0.1)
t1 = default_timer()

pp.title('Single Plot extended call')

print 'Execution time for extended call plotting = %f sec' % (t1-t0)

############################
# rebuild ends using none to separate line segments
xlist = []
ylist = []
for xends,yends in zip(xpairs,ypairs):
xlist.extend(xends)
xlist.append(None)
ylist.extend(yends)
ylist.append(None)

############################
# time single call to matplotlib
pp.subplot(1,3,3)

t0 = default_timer()
pp.plot(xlist,ylist,'b-',alpha=0.1)
t1 = default_timer()

pp.title('Single Plot Using None')

print 'Execution time when using None = %f sec' % (t1-t0)

pp.show()

## Discussion:

Sequential call and extended call syntax produce the same results. However, the single list of points using ‘None’ can generate a different image if transparency is used. In the sample code, ‘alpha=0.1’ was used. When sequential plots or extended call syntax is used, the color from each line segment is additive. When the line segments were combined into a single list of points, the line segments’ color was not additive. This is only an issue when using transparency. If alpha is set to 1.0 (or not set at all), then all of the plots will be identical.

## Test Conditions:

• How to speed up Matplotlib plots
• How to plot lines in Matplotlib

1. This worked wonderfully for my application, thanks for the tip!

2. Hello there,

nice article! I found yet another method to draw the lines using linecollection. On my maschine, the times read
Execution time for sequential plotting = 1.308422 sec
Execution time for extended call plotting = 0.773470 sec
Execution time when using None = 0.016326 sec
Execution time when using LineCollection = 0.080493 sec
putting LineCollection in second place overall or in first place considering only solutions with additive color!

@imports:
from matplotlib.collections import LineCollection

@rebuild ends using none to separate line segments
xlist = []
ylist = []
linecol = []
for xends,yends in zip(xpairs,ypairs):
xlist.extend(xends)
xlist.append(None)
ylist.extend(yends)
ylist.append(None)
linecol.append((xends,yends))

@just before the pp.show() command
# time single call to matplotlib with LineCollection
axes = pp.subplot(2,2,4)

t0 = default_timer()
lines = LineCollection(linecol,alpha=0.1)
4. what is you use nan in ylist instead of None? it has same effect but works naturally with arrays.