ztl
ztl

Reputation: 2592

Matplotlib: combine different lines into a single object to be plotted many times

In matplotlib, how could I combine a series of X-Y values (each of them being for example in an array or list) to be plotted together many times later (with other elements, this is a general pattern over which different things are to be plotted)?

I would like to compute/extract them once, then combine them in a single object/shape to be plotted properly in one command instead of always having to plot them separately:

import matplotlib.pyplot as plt
import numpy

# Simple example
numpy.random.seed(4)
x = range(10)
y = numpy.random.rand(10)

# Create three 'lines' (here, as x-y arrays) with different lenghts
a = numpy.array((x, y*10)).T
b = numpy.array((x[:5]*y[:5], y[:5]**2)).T
c = numpy.array((x[3:7], x[3:7])).T

# Combine a, b, and c in one object to be called many times later
# (this is not a good way to do that)
abc = numpy.concatenate((a, b, c))

# Plot
fig = plt.figure(figsize=(9,3))

ax0 = fig.add_subplot(131)
ax0.plot(a[:,0], a[:,1], color='b')
ax0.plot(b[:,0], b[:,1], color='r')
ax0.plot(c[:,0], c[:,1], color='g')
ax0.set_title("3 lines to be combined")

ax1 = fig.add_subplot(132)
ax1.plot(a[:,0], a[:,1], color='b')
ax1.plot(b[:,0], b[:,1], color='b')
ax1.plot(c[:,0], c[:,1], color='b')
ax1.set_title("Desired output")

ax2 = fig.add_subplot(133)
ax2.plot(abc[:,0], abc[:,1], color='b') # 1-line command
ax2.set_title("Wrong (spaghetti plot)")

enter image description here

EDIT

Tom's answer solves my problem nicely, building up on my attempt above (i.e., concantenate in a single array). Any other solution with a different approach remains welcome to learn something new (e.g., is it possible to build a single matplotlib object (an Artist or so)?).

Upvotes: 1

Views: 3344

Answers (1)

tmdavison
tmdavison

Reputation: 69106

If all you want is a one line way to plot a, b and c, you can do this:

ax2.plot(a[:,0], a[:,1], b[:,0], b[:,1], c[:,0], c[:,1], color='b')

EDIT:

To use a single object that still has line breaks between the original objects, you could use numpy.NaN to break the line.

import matplotlib.pyplot as plt
import numpy

# Simple example
numpy.random.seed(4)
x = range(10)
y = numpy.random.rand(10)

# Create three 'lines' (here, as x-y arrays) with different lenghts
a = numpy.array((x, y*10)).T
b = numpy.array((x[:5]*y[:5], y[:5]**2)).T
c = numpy.array((x[3:7], x[3:7])).T

# Use this to break up the original objects. 
# plt.plot does not like NaN's, so will break the line there.
linebreak=[[numpy.NaN,numpy.NaN]]

# Combine a, b, and c in one object to be called many times later
abc = numpy.concatenate((a, linebreak, b, linebreak, c))

# Plot
fig = plt.figure(figsize=(9,3))

ax0 = fig.add_subplot(131)
ax0.plot(a[:,0], a[:,1], color='b')
ax0.plot(b[:,0], b[:,1], color='r')
ax0.plot(c[:,0], c[:,1], color='g')
ax0.set_title("3 lines to be combined")

ax1 = fig.add_subplot(132)
ax1.plot(a[:,0], a[:,1], color='b')
ax1.plot(b[:,0], b[:,1], color='b')
ax1.plot(c[:,0], c[:,1], color='b')
ax1.set_title("Desired output")

ax2 = fig.add_subplot(133)
ax2.plot(abc[:,0], abc[:,1], color='b') # 1-line command
ax2.set_title("Single object with breaks")

enter image description here

Upvotes: 2

Related Questions