Python 在 Matplotlib 中重置颜色循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24193174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 04:10:24  来源:igfitidea点击:

Reset color cycle in Matplotlib

pythonmatplotlibpandas

提问by 8one6

Say I have data about 3 trading strategies, each with and without transaction costs. I want to plot, on the same axes, the time series of each of the 6 variants (3 strategies * 2 trading costs). I would like the "with transaction cost" lines to be plotted with alpha=1and linewidth=1while I want the "no transaction costs" to be plotted with alpha=0.25and linewidth=5. But I would like the color to be the same for both versions of each strategy.

假设我有关于 3 种交易策略的数据,每种策略都有交易成本和没有交易成本。我想在相同的轴上绘制 6 个变体(3 个策略 * 2 个交易成本)中每一个的时间序列。我想“与交易成本”线与绘制alpha=1,并linewidth=1同时我想“无交易成本”与绘制alpha=0.25linewidth=5。但我希望每种策略的两个版本的颜色都相同。

I would like something along the lines of:

我想要一些类似的东西:

fig, ax = plt.subplots(1, 1, figsize=(10, 10))

for c in with_transaction_frame.columns:
    ax.plot(with_transaction_frame[c], label=c, alpha=1, linewidth=1)

****SOME MAGIC GOES HERE TO RESET THE COLOR CYCLE

for c in no_transaction_frame.columns:
    ax.plot(no_transaction_frame[c], label=c, alpha=0.25, linewidth=5)

ax.legend()

What is the appropriate code to put on the indicated line to reset the color cycle so it is "back to the start" when the second loop is invoked?

在指定的行上放置以重置颜色循环以便在调用第二个循环时“回到起点”的适当代码是什么?

采纳答案by pelson

You can reset the colorcycle to the original with Axes.set_color_cycle. Looking at the code for this, there is a function to do the actual work:

您可以使用 Axes.set_color_cycle 将颜色循环重置为原始颜色。查看此代码,有一个函数可以完成实际工作:

def set_color_cycle(self, clist=None):
    if clist is None:
        clist = rcParams['axes.color_cycle']
    self.color_cycle = itertools.cycle(clist

And a method on the Axes which uses it:

以及使用它的 Axes 上的方法:

def set_color_cycle(self, clist):
    """
    Set the color cycle for any future plot commands on this Axes.

    *clist* is a list of mpl color specifiers.
    """
    self._get_lines.set_color_cycle(clist)
    self._get_patches_for_fill.set_color_cycle(clist)

This basically means you can call the set_color_cycle with None as the only argument, and it will be replaced with the default cycle found in rcParams['axes.color_cycle'].

这基本上意味着您可以使用 None 作为唯一参数调用 set_color_cycle,它将被替换为 rcParams['axes.color_cycle'] 中的默认循环。

I tried this with the following code and got the expected result:

我用下面的代码尝试了这个并得到了预期的结果:

import matplotlib.pyplot as plt
import numpy as np

for i in range(3):
    plt.plot(np.arange(10) + i)

# for Matplotlib version < 1.5
plt.gca().set_color_cycle(None)
# for Matplotlib version >= 1.5
plt.gca().set_prop_cycle(None)

for i in range(3):
    plt.plot(np.arange(10, 1, -1) + i)

plt.show()

Code output, showing the color cycling reset functionality

代码输出,显示颜色循环重置功能

回答by Ffisegydd

Simply choose your colours and assign them to a list, then when you plot your data iterate over a zipobject containing your column and the colour you wish.

只需选择您的颜色并将它们分配给一个列表,然后当您绘制数据时,迭代zip包含您的列和您想要的颜色的对象。

colors = ['red', 'blue', 'green']

for col, color in zip(colors, with_transaction_frame.columns):
    ax.plot(with_transaction_frame[col], label=col, alpha=1.0, linewidth=1.0, color=color)

for col, color in zip(no_transaction_frame.columns):
    ax.plot(no_transaction_frame[col], label=col, alpha=0.25, linewidth=5, color=color)

zipcreates a list that aggregates the elements from each of your lists. This allows you to iterate over both easily at the same time.

zip创建一个列表,聚合每个列表中的元素。这使您可以轻松地同时迭代两者。

回答by mwaskom

Since you mentioned you're using seaborn, what I would recommend doing is:

既然你提到你正在使用 seaborn,我建议你做的是:

with sns.color_palette(n_colors=3):

    ax.plot(...)
    ax.plot(...)

This will set the color palette to use the currently active color cycle, but only the first three colors from it. It's also a general purpose solution for any time you want to set a temporary color cycle.

这会将调色板设置为使用当前活动的颜色循环,但仅使用其中的前三种颜色。它也是您想要设置临时颜色循环的任何时候的通用解决方案。

Note that the only thing that actually needs to be under the withblock is whatever you are doing to create the Axesobject (i.e. plt.subplots, fig.add_subplot(), etc.). This is just because of how the matplotlib color cycle itself works.

需要注意的是,实际需要是下唯一with块是无论你正在做的创建Axes对象(也就是plt.subplotsfig.add_subplot()等)。这只是因为 matplotlib 颜色循环本身的工作方式。

Doing what you specifically want, "resetting" the color cycle, is possible, but it's a hack and I wouldn't do it in any kind of production code. Here, though, is how it could happen:

做你特别想要的,“重置”颜色循环,是可能的,但这是一个黑客,我不会在任何类型的生产代码中这样做。然而,这就是它可能发生的方式:

f, ax = plt.subplots()
ax.plot(np.random.randn(10, 3))
ax._get_lines.color_cycle = itertools.cycle(sns.color_palette())
ax.plot(np.random.randn(10, 3), lw=5, alpha=.25)

enter image description here

在此处输入图片说明

回答by Brad Campbell

You can get the colors from seaborn like this: colors = sns.color_palette(). Ffisegydd's answer would then work great. You could also get the color to plot using the modulus/remainder operater (%): mycolor = colors[icolumn % len(colors]. I use often use this approach myself. So you could do:

你可以得到颜色seaborn这样的:colors = sns.color_palette()。Ffisegydd 的回答会很有效。您还可以使用模数/余数运算符 (%) 获取要绘制的颜色:mycolor = colors[icolumn % len(colors]。我自己经常使用这种方法。所以你可以这样做:

for icol, column in enumerate(with_transaction_frame.columns): mycolor = colors[icol % len(colors] ax.plot(with_transaction_frame[col], label=col, alpha=1.0, color=mycolor)

for icol, column in enumerate(with_transaction_frame.columns): mycolor = colors[icol % len(colors] ax.plot(with_transaction_frame[col], label=col, alpha=1.0, color=mycolor)

Ffisegydd's answer may be more 'pythonic', though.

不过,Ffisegydd 的回答可能更“pythonic”。

回答by Ramon Crehuet

As the answer given by @pelson uses set_color_cycleand this is deprecated in Matplotlib 1.5, I thought it would be useful to have an updated version of his solution using set_prop_cycle:

正如@pelson 给出的答案所使用的set_color_cycle,这在 Matplotlib 1.5 中已被弃用,我认为使用他的解决方案的更新版本会很有用set_prop_cycle

import matplotlib.pyplot as plt
import numpy as np

for i in range(3):
    plt.plot(np.arange(10) + i)

plt.gca().set_prop_cycle(None)

for i in range(3):
    plt.plot(np.arange(10, 0, -1) + i)

plt.show()

Remark also that I had to change np.arange(10,1,-1)to np.arange(10,0,-1). The former gave an array of only 9 elements. This probably arises from using different Numpy versions. Mine is 1.10.2.

另请注意,我必须更改np.arange(10,1,-1)np.arange(10,0,-1). 前者给出了一个只有 9 个元素的数组。这可能是由于使用了不同的 Numpy 版本。我的是 1.10.2。

EDIT: Removed the need to use rcParams. Thanks to @divenex for pointing that out in a comment.

编辑:删除了使用的需要rcParams。感谢@divenex 在评论中指出这一点。

回答by warped

As an addition to the already excellent answers, you can consider using a colormap:

作为已经很好的答案的补充,您可以考虑使用颜色图:

import matplotlib.pyplot as plt
import numpy as np

cmap = plt.cm.viridis

datarange = np.arange(4)

for d in datarange:
    # generate colour by feeding float between 0 and 1 to colormap
    color = cmap(d/np.max(datarange)) 
    plt.plot(np.arange(5)+d, c=color)

for d in datarange:
    # generate colour by feeding float between 0 and 1 to colormap
    color = cmap(d/np.max(datarange))
    plt.plot(-np.arange(5)+d, c=color)

enter image description here

在此处输入图片说明