在Matplotlib中重置颜色循环

时间:2014-06-12 20:13:45

标签: python matplotlib pandas

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

我想要的是:

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()

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

6 个答案:

答案 0 :(得分:61)

您可以使用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

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)

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

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

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

答案 1 :(得分:20)

由于@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()

另请注意,我必须将np.arange(10,1,-1)更改为np.arange(10,0,-1)。前者只提供了9个元素。这可能源于使用不同的Numpy版本。我的是1.10.2。

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

答案 2 :(得分:5)

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

with sns.color_palette(n_colors=3):

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

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

请注意,with块下实际需要的唯一内容就是您在创建Axes对象时所做的一切(即plt.subplotsfig.add_subplot()等)。这只是因为matplotlib颜色循环本身的工作原理。

做你特别想要的,“重置”色彩循环是可能的,但这是一个黑客,我不会在任何类型的生产代码中做到这一点。不过,这是怎么回事:

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

答案 3 :(得分:2)

只需选择颜色并将它们分配到列表中,然后在绘制数据时,迭代一个包含您的列和所需颜色的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)

zip创建一个列表,汇总每个列表中的元素。这允许您同时轻松地迭代这两者。

答案 4 :(得分:2)

你可以从这样的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)

Ffisegydd的回答可能更多是“pythonic&#39;”。

答案 5 :(得分:0)

除了已经很好的答案之外,您还可以考虑使用颜色图:

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