7

I have an array of y-values that form a line. Additionally, I have an array with the same number of elements as the y-array of values ranging from 0 to 1. We'll call this array 'z'. I want to plot the array of y-values so that the color of each point corresponds with the z-value.

In gnuplot, you can do this using the 'lc variable':

plot ’data’ using 1:2:3 with points lc variable  

Using the advice from here: Matplotlib scatterplot; colour as a function of a third variable , I was able to use a scatter plot, which did work:

import matplotlib as mpl  
import matplotlib.pyplot as plt  

plt.scatter(x, y, c=z, s=1, edgecolors='none', cmap=mpl.cm.jet)  
plt.colorbar()  
plt.show()  

Is there a way to do this with the plot method in matplotlib, similar to this?

plt.plot(x, y, c=z)

When I tried the above code, all of the lines just appeared black.

1
  • In gnuplot lc variable selects the line type index based on the value of the last column. To use it as a color, use e.g. lc palette z. Commented Aug 30, 2013 at 11:15

2 Answers 2

19

I had the same problem: wanted to plot line(s) with non-uniform color, which I wanted to be dependent on a third variable (z).

But I definitelly wanted to use a line, not markers (as in @joaquin's answer). I found a solution in a matplotlib gallery example, using the class matplotlib.collections.LineCollection (link here).

Here is my example, which plots trajectories in a Basemap, coloring them according to its height:

import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib.collections import LineCollection
import numpy as np

m = Basemap(llcrnrlon=-42,llcrnrlat=0,urcrnrlon=5,urcrnrlat=50, resolution='h')
fig = plt.figure()
m.drawcoastlines()
m.drawcountries()

for i in trajectorias:
    # for each i, the x (longitude), y (latitude) and z (height)
    # are read from a file and stored as numpy arrays

    points = np.array([x, y]).T.reshape(-1, 1, 2)
    segments = np.concatenate([points[:-1], points[1:]], axis=1)

    lc = LineCollection(segments, cmap=plt.get_cmap('Spectral'),
                        norm=plt.Normalize(250, 1500))
    lc.set_array(z)
    lc.set_linewidth(2)

    plt.gca().add_collection(lc)

axcb = fig.colorbar(lc)
axcb.set_label('cota (m)')

plt.show()

height dependent trajectories

Sign up to request clarification or add additional context in comments.

2 Comments

If you want a smoother transition between line segments you can do segments = np.concatenate([points[:-2], points[1:-1], points[2:]], axis=1) instead.
I'm trying to plot a time-series where the vertical axis is the vertical displacement of particles and I would like to use other property (mass) as the colormap. I'm getting the error: 'TypeError: float() argument must be a string or a number, not 'datetime.datetime'. Any tips of how to solve it?
2

you can use scatter:

plt.scatter(range(len(y)), y, c=z, cmap=cm.hot)

here you have the ipython -pylab session:

In [27]: z = [0.3,0.4,0.5,0.6,0.7,0.2,0.3,0.4,0.5,0.8,0.9]

In [28]: y = [3, 7, 5, 6, 4, 8, 3, 4, 5, 2, 9]

In [29]: plt.scatter(range(len(y)), y, s=60, c=z, cmap=cm.hot)
Out[29]: <matplotlib.collections.PathCollection at 0x9ec8400>

enter image description here

If you want to use plot you can get the equivalent figure as above with (pycrust session):

>>> from matplotlib import pyplot as plt
>>> from matplotlib import cm
>>> y = [3,7,5,6,4,8,3,4,5,2,9]
>>> z = [0.3,0.4,0.5,0.6,0.7,0.2,0.3,0.4,0.5,0.8,0.9]
>>> for x, (v, c) in enumerate(zip(y,z)):
...      plt.plot(x,v,marker='o', color=cm.hot(c))
...      
[<matplotlib.lines.Line2D object at 0x0000000008C42518>]
[<matplotlib.lines.Line2D object at 0x0000000008C426D8>]
[<matplotlib.lines.Line2D object at 0x0000000008C42B38>]
[<matplotlib.lines.Line2D object at 0x0000000008C452B0>]
[<matplotlib.lines.Line2D object at 0x0000000008C45438>]
[<matplotlib.lines.Line2D object at 0x0000000008C45898>]
[<matplotlib.lines.Line2D object at 0x0000000008C45CF8>]
[<matplotlib.lines.Line2D object at 0x0000000008C48198>]
[<matplotlib.lines.Line2D object at 0x0000000008C485F8>]
[<matplotlib.lines.Line2D object at 0x0000000008C48A58>]
[<matplotlib.lines.Line2D object at 0x0000000008C4B1D0>]
>>> plt.show()
>>> 

1 Comment

Thanks joaquin. I've decided to use scatter instead of plot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.