How to set same color for markers and lines in a matplotlib plot loop?

Question:

I have to plot multiple lines and markers with matplotlib by creating a loop and I have already set the axes color cycle in the matplolibrc param file. In each cycle of the loop a set of markers and lines are created (lines are created by a separate command). But the marker and line colors are different as per the axes color cycle. I want each time the loop is run the marker and lines to be of the same color of that cycle.

I have included the reproducible code:

import numpy as np
import itertools
import matplotlib.pyplot as plt
m = 5
n = 5
x = np.zeros(shape=(m, n))
plt.figure(figsize=(5.15, 5.15))
plt.clf()
plt.subplot(111)
marker = itertools.cycle(('o', 'v', '^', '<', '>', 's', '8', 'p'))
for i in range(1, n):
    x = np.dot(i, [1, 1.1, 1.2, 1.3])
    y = x ** 2
    plt.plot(x, y, linestyle='', markeredgecolor='none', marker=marker.next())
    plt.plot(x, y, linestyle='-')
plt.ylabel(r'textit{y}', labelpad=6)
plt.xlabel(r'textit{x}', labelpad=6)
plt.show()

Using this code the output I get is:

enter image description here

I need the markers and lines plotted in their range to be of the same color. How can it be done in matplotlib?

Asked By: Tom Kurushingal

||

Answers:

I present two ways. The first is probably cleaner: it loops through once, and within each loop, gets the next color, and then does two plotting commands with that color. In the second, it loops through and does all the markers and then it resets the colors and loops through again and does the lines.

first method

Directly access the color cycle. If matplotlib 1.5 or later use color=next(ax._get_lines.prop_cycler)['color']. Otherwise color=next(ax._get_lines.color_cycle):

import numpy as np
import itertools
import matplotlib.pyplot as plt
m = 5
n = 5
x = np.zeros(shape=(m, n))
plt.figure(figsize=(5.15, 5.15))
plt.clf()
plt.subplot(111)
marker = itertools.cycle(('o', 'v', '^', '<', '>', 's', '8', 'p'))

ax = plt.gca()
for i in range(1, n):
    x = np.dot(i, [1, 1.1, 1.2, 1.3])
    y = x ** 2
    #
    #for matplotlib before 1.5, use
    #color = next(ax._get_lines.color_cycle)
    #instead of next line (thanks to Jon Loveday for the update)
    #
    color = next(ax._get_lines.prop_cycler)['color']
    plt.plot(x, y, linestyle='', markeredgecolor='none', marker=marker.next(), color=color)
    plt.plot(x, y, linestyle='-', color = color)
plt.ylabel(r'$y$', labelpad=6)
plt.xlabel(r'$x$', labelpad=6)
plt.savefig('test2.png')

Also, notice I changed your textit{y} to $y$. Usually you actually want math fonts rather than italics.

enter image description here

second method

If you don’t want to send a color in as an argument, you can reset the color cycle and go through the loop twice. Here I reset it before the first loop and then again before the second loop just to make sure it’s starting from the same place.

import numpy as np
import itertools
import matplotlib.pyplot as plt
m = 5
n = 5
x = np.zeros(shape=(m, n))
plt.figure(figsize=(5.15, 5.15))
plt.clf()
plt.subplot(111)
marker = itertools.cycle(('o', 'v', '^', '<', '>', 's', '8', 'p'))

plt.gca().set_prop_cycle(None) #if matplotlib <1.5 use set_color_cycle
for i in range(1, n):
    x = np.dot(i, [1, 1.1, 1.2, 1.3])
    y = x ** 2
    plt.plot(x, y, linestyle='', markeredgecolor='none', marker=marker.next())
plt.gca().set_prop_cycle(None)
for i in range(1, n):
    x = np.dot(i, [1, 1.1, 1.2, 1.3])
    y = x ** 2
    plt.plot(x, y, linestyle='-')
plt.ylabel(r'$y$', labelpad=6)
plt.xlabel(r'$x$', labelpad=6)
plt.savefig('test.png')

enter image description here

Answered By: Joel

Note that in matplotlib 1.5 onwards, color_cycle has been replaced by prop_cycler. The first option then needs:

color = next(ax._get_lines.prop_cycler)['color']
Answered By: Jon Loveday

Note that iter.next() was removed in Python 3.x as described in this question. If you run the examples in the accepted answer you will therefore receive AttributeError:

'itertools.cycle' object has no attribute 'next'

For both examples this can be solved by replacing:

marker=marker.next()

in plt.plot() with

marker=next(marker)
Answered By: Adriaan

Here is my very basic solution:

Just read the color from the previous plot with .get_color() and hand it over to the next one with the keyword color:

import numpy as np
import itertools
import matplotlib.pyplot as plt
m = 5
n = 5
x = np.zeros(shape=(m, n))
plt.figure(figsize=(5.15, 5.15))
plt.clf()
plt.subplot(111)
marker = itertools.cycle(('o', 'v', '^', '<', '>', 's', '8', 'p'))
for i in range(1, n):
    x = np.dot(i, [1, 1.1, 1.2, 1.3])
    y = x ** 2
    lines = plt.plot(x, y, linestyle='', markeredgecolor='none', marker=next(marker))
    linecolor = lines[0].get_color()
    plt.plot(x, y, linestyle='-',color=linecolor)
plt.ylabel(r'$y$', labelpad=6)
plt.xlabel(r'$x$', labelpad=6)
plt.show()

As noted in this answer, the code was updated to run in Python 3.x.

You may also get what you want with the plt.plot keyword markevery=..., demonstrated here.

Answered By: n4pK
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.