2

I want to use the next color for each plot that I plot by for loop. But when I call ax1._get_lines.prop_cycler.next(), it cannot go to the third color. How to do something like .next().next() or ax1._get_lines.prop_cycler.next()[k] in the loop line by using k in xrange() ?

a = np.cumsum(np.cumsum(np.random.randn(7,4), axis=0), axis=1)

lab = np.array(["A","B","C","E"])

for k in xrange(4):
    ax1 = plt.subplot2grid((4, 1), (k, 0), rowspan=1, colspan=4)
    ax1._get_lines.prop_cycler.next()
    ax1.plot(a[:,k])
    plt.legend(labels=lab[k:k+1])

plt.show()

enter image description here

Jan
  • 1,389
  • 4
  • 17
  • 43

2 Answers2

2

In the code from the question, each subplot has its own colorcycle, such that next gives you the second color of the axes' colorcycle in each subplot.

A solution would be to share the same color cycle among all subplots.

For the case where you create the subplots inside the loop, you might use

import matplotlib.pyplot as plt
import numpy as np

a = np.cumsum(np.cumsum(np.random.randn(7,4), axis=0), axis=1)

lab = np.array(["A","B","C","E"])

for k in xrange(4):
    ax1 = plt.subplot2grid((4, 1), (k, 0))
    if k==0:
        c = ax1._get_lines.prop_cycler
    else:
        ax1._get_lines.prop_cycler = c
    ax1.plot(a[:,k])
    plt.legend(labels=lab[k:k+1])

plt.show()

Or in a case where subplots are created all at once,

import matplotlib.pyplot as plt
import numpy as np

a = np.cumsum(np.cumsum(np.random.randn(7,4), axis=0), axis=1)

lab = np.array(["A","B","C","E"])

fig, axes = plt.subplots(4,1)
for k, ax in enumerate(axes):
    ax._get_lines.prop_cycler = axes[0]._get_lines.prop_cycler
    ax.plot(a[:,k])
    ax.legend(labels=lab[k])

plt.show()

Of course you could also use the color cycler from each axes individually and propagate it to the next color

import matplotlib.pyplot as plt
import numpy as np

a = np.cumsum(np.cumsum(np.random.randn(7,4), axis=0), axis=1)

lab = np.array(["A","B","C","E"])

fig, axes = plt.subplots(4,1)
for k, ax in enumerate(axes):
    for i in range(k):
        next(ax._get_lines.prop_cycler)
    ax.plot(a[:,k])
    ax.legend(labels=lab[k])

plt.show()

In all cases the result would look like this:

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
1

The problem with your code is that you create a new axes instance in every loop and then you do ax1._get_lines.prop_cycler.next(). Since ax1 is a new object every time, you always get the same color.

The best solution is to explicitly pass the color to the plot. You should be able to obtain what you want with the following code, inspired by this example:

import numpy as np
import matplotlib.pyplot as plt

a = np.cumsum(np.cumsum(np.random.randn(7,4), axis=0), axis=1)
lab = np.array(["A","B","C","E"])

colors = plt.rcParams['axes.prop_cycle'] 
colors = colors.by_key()['color']

for (k, label), color in zip(enumerate(lab), colors):
    ax1 = plt.subplot2grid((4, 1), (k, 0), rowspan=1, colspan=4)
    ax1.plot(a[:,k], color=color)
    plt.legend(labels=label)

plt.show()

Note: my version of the code also avoids xrange and the next() method that fail in python3.


A warning: in your example, you use ax1._get_lines. Usually names starting with an underscore are considered private: therefore the matplotlib developers might change or remove the attribute _get_lines at any time without notice and break your code. I suggest you to make use of the public API as much as possible.

Francesco Montesano
  • 8,485
  • 2
  • 40
  • 64