Reset color cycle in Matplotlib

前端 未结 6 1057
北恋
北恋 2020-11-27 04:12

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 strategi

相关标签:
6条回答
  • 2020-11-27 04:27

    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:

    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.

    0 讨论(0)
  • 2020-11-27 04:32

    As the answer given by @pelson uses set_color_cycle and 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:

    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.

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

    0 讨论(0)
  • 2020-11-27 04:39

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

    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 creates a list that aggregates the elements from each of your lists. This allows you to iterate over both easily at the same time.

    0 讨论(0)
  • 2020-11-27 04:42

    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:

    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:

    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'].

    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

    0 讨论(0)
  • 2020-11-27 04:48

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

    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 with block is whatever you are doing to create the Axes object (i.e. plt.subplots, fig.add_subplot(), etc.). This is just because of how the matplotlib color cycle itself works.

    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

    0 讨论(0)
  • 2020-11-27 04:49

    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)
    

    0 讨论(0)
提交回复
热议问题