plotting different colors in matplotlib [duplicate]

Suppose I have a for loop and I want to plot points in different colors:

for i in range(5):
 plt.plot(x,y,col=i)

How do I automatically change colors in the for loop?


Solution 1:

@tcaswell already answered, but I was in the middle of typing my answer up, so I'll go ahead and post it...

There are a number of different ways you could do this. To begin with, matplotlib will automatically cycle through colors. By default, it cycles through blue, green, red, cyan, magenta, yellow, black:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 1, 10)
for i in range(1, 6):
    plt.plot(x, i * x + i, label='$y = {i}x + {i}$'.format(i=i))
plt.legend(loc='best')
plt.show()

enter image description here

If you want to control which colors matplotlib cycles through, use ax.set_color_cycle:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 1, 10)
fig, ax = plt.subplots()
ax.set_color_cycle(['red', 'black', 'yellow'])
for i in range(1, 6):
    plt.plot(x, i * x + i, label='$y = {i}x + {i}$'.format(i=i))
plt.legend(loc='best')
plt.show()

enter image description here

If you'd like to explicitly specify the colors that will be used, just pass it to the color kwarg (html colors names are accepted, as are rgb tuples and hex strings):

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 1, 10)
for i, color in enumerate(['red', 'black', 'blue', 'brown', 'green'], start=1):
    plt.plot(x, i * x + i, color=color, label='$y = {i}x + {i}$'.format(i=i))
plt.legend(loc='best')
plt.show()

enter image description here

Finally, if you'd like to automatically select a specified number of colors from an existing colormap:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 1, 10)
number = 5
cmap = plt.get_cmap('gnuplot')
colors = [cmap(i) for i in np.linspace(0, 1, number)]

for i, color in enumerate(colors, start=1):
    plt.plot(x, i * x + i, color=color, label='$y = {i}x + {i}$'.format(i=i))
plt.legend(loc='best')
plt.show()

enter image description here

Solution 2:

Joe Kington's excellent answer is already 4 years old, Matplotlib has incrementally changed (in particular, the introduction of the cycler module) and the new major release, Matplotlib 2.0.x, has introduced stylistic differences that are important from the point of view of the colors used by default.

The color of individual lines

The color of individual lines (as well as the color of different plot elements, e.g., markers in scatter plots) is controlled by the color keyword argument,

plt.plot(x, y, color=my_color)

my_color is either

  • a tuple of floats representing RGB or RGBA (as(0.,0.5,0.5)),
  • a RGB/RGBA hex string (as "#008080" (RGB) or "#008080A0"),
  • a string representation of a float value in [0, 1] inclusive for gray level (e.g., '0.6'),
  • a short color name (as "k" for black, possible values in "bgrcmykw"),
  • a long color name (as "teal") --- aka HTML color name (in the docs also X11/CSS4 color name),
  • a name from the xkcd color survey, prefixed with 'xkcd:' (e.g., 'xkcd:barbie pink'),
  • a color from the Tableau Colors in the default 'T10' categorical palette, (e.g., 'tab:blue', 'tab:olive'),
  • a reference to a color of the current color cycle (as "C3", i.e., the letter "C" followed by a single digit in "0-9").

The color cycle

By default, different lines are plotted using different colors, that are defined by default and are used in a cyclic manner (hence the name color cycle).

The color cycle is a property of the axes object, and in older releases was simply a sequence of valid color names (by default a string of one character color names, "bgrcmyk") and you could set it as in

my_ax.set_color_cycle(['kbkykrkg'])

(as noted in a comment this API has been deprecated, more on this later).

In Matplotlib 2.0 the default color cycle is ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"], the Vega category10 palette.

enter image description here

(the image is a screenshot from https://vega.github.io/vega/docs/schemes/)

The cycler module: composable cycles

The following code shows that the color cycle notion has been deprecated

In [1]: from matplotlib import rc_params

In [2]: rc_params()['axes.color_cycle']
/home/boffi/lib/miniconda3/lib/python3.6/site-packages/matplotlib/__init__.py:938: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
  warnings.warn(self.msg_depr % (key, alt_key))
Out[2]: 
['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd',
 '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf']

Now the relevant property is the 'axes.prop_cycle'

In [3]: rc_params()['axes.prop_cycle']
Out[3]: cycler('color', ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'])

Previously, the color_cycle was a generic sequence of valid color denominations, now by default it is a cycler object containing a label ('color') and a sequence of valid color denominations. The step forward with respect to the previous interface is that it is possible to cycle not only on the color of lines but also on other line attributes, e.g.,

In [5]: from cycler import cycler

In [6]: new_prop_cycle = cycler('color', ['k', 'r']) * cycler('linewidth', [1., 1.5, 2.])

In [7]: for kwargs in new_prop_cycle: print(kwargs)
{'color': 'k', 'linewidth': 1.0}
{'color': 'k', 'linewidth': 1.5}
{'color': 'k', 'linewidth': 2.0}
{'color': 'r', 'linewidth': 1.0}
{'color': 'r', 'linewidth': 1.5}
{'color': 'r', 'linewidth': 2.0}

As you have seen, the cycler objects are composable and when you iterate on a composed cycler what you get, at each iteration, is a dictionary of keyword arguments for plt.plot.

You can use the new defaults on a per axes object ratio,

my_ax.set_prop_cycle(new_prop_cycle)

or you can install temporarily the new default

plt.rc('axes', prop_cycle=new_prop_cycle)

or change altogether the default editing your .matplotlibrc file.

Last possibility, use a context manager

with plt.rc_context({'axes.prop_cycle': new_prop_cycle}):
    ...

to have the new cycler used in a group of different plots, reverting to defaults at the end of the context.

The doc string of the cycler() function is useful, but the (not so much) gory details about the cycler module and the cycler() function, as well as examples, can be found in the fine docs.