0

Matplotlib in python takes sequences of x and y values to produce a plot of data.

We can specify a color for the particular graph being plotted. However, since we are plotting an explicit list of dots, I wonder if there is a way to specify the color for each point individually?

For example, how can I make the points plotted in the following graph each have a specific random color?

import matplotlib.pyplot as plt
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title('A single color plot')

enter image description here

7
  • i don't see points Commented Jan 27, 2020 at 0:33
  • 2
    You're not plotting points, you plot a line. If you wanted to plot points you could use ax.scatter. If instead you want individual line segments to be colorized, you can use a LineCollection as shown e.g. in this Q&A. Commented Jan 27, 2020 at 0:36
  • @ImportanceOfBeingErnest Oh, ok, I'm happy with a scatter plot, too, if it can take individual colors for each point. How should I do that? Commented Jan 27, 2020 at 0:38
  • 2
    ax.scatter(x,y, c=np.random.rand(len(x), 3)) Commented Jan 27, 2020 at 0:41
  • 2
    plot creates a Line2D object, which is optimized for fast drawing. It would be bad style to let the same command plot return different objects, depending on the input. That's why there is LineCollection, which can be used if different segments are supposed to have different properties. Commented Jan 27, 2020 at 1:10

1 Answer 1

3

Following the links and suggestions of ImportanceOfBeingErnest in the comments, I pieced together the following solution for the case when a plot of line segments of different color is required.

Ideally, I would have wished each point to be of a particular color and the line segments to smoothly interpolate in the color-spectrum between these respective colors. But I guess, matplotlib is free software, so it's not too surprising that it does not have the most fancy features. Unless, of course, if it can be done, but I don't know how?

import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
x = np.linspace(0, 2 * np.pi, 400)
y = np.sin(x ** 2)
xy = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.hstack([xy[:-1], xy[1:]])
fig, ax = plt.subplots()
lc = LineCollection(segments, colors=np.random.rand(len(segments), 3))
ax.add_collection(lc)
ax.autoscale()
ax.set_title('A multi-color plot')
plt.show()

enter image description here

EDIT:

Just for fun, doing more steps and creating a gradient "by hand", as ImportanceOfBeingErnest suggested, we can get e.g. something like this:

import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
x = [0.]
while x[-1]<2 * np.pi :
    x.append(x[-1] +1/(100*np.sqrt(1+4*x[-1]*x[-1]*np.cos(x[-1]*x[-1])*np.cos(x[-1]*x[-1]))))
x = np.array(x)
y = np.sin(x ** 2)
xy = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.hstack([xy[:-1], xy[1:]])
myColors = np.random.rand(len(segments), 3)
for i in range(len(segments)//10):
    for j in range(9):
        myColors[10*i+j+1] = myColors[10*i]+(myColors[10*(i+1)]-myColors[10*i])*(j+1)/10
fig, ax = plt.subplots()
lc = LineCollection(segments, colors=myColors)
ax.add_collection(lc)
ax.autoscale()
ax.set_title('A multi-color plot')
plt.show()

enter image description here

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

2 Comments

It can be done of course. You would divide each segment again into several shorter ones, each with a color interpolated between the two end point colors.
@ImportanceOfBeingErnest oh, ok, I see. I was kind of hoping there would be an automatic blender of some sort, which would make the process simpler... I mean, ideally one would need a continuous color gradient, which is hardly feasible with discrete methods applied "by hand".

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.