use matplotlib color map for color cycle

后端 未结 3 415
夕颜
夕颜 2020-11-30 05:29

If I create colors by e.g:

import numpy as np
from matplotlib import pyplot as plt

n = 6
color = plt.cm.coolwarm(np.linspace(0.1,0.9,n))
color
相关标签:
3条回答
  • 2020-11-30 05:33

    The details are in the matplotlibrc itself, actually: it needs a string rep (hex or letter or word, not tuple).

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    
    fig, ax1 = plt.subplots(1,1)
    
    ys = np.random.random((5, 6))
    ax1.plot(range(5), ys)
    ax1.set_title('Default color cycle')
    plt.show()
    
    # From the sample matplotlibrc:
    #axes.color_cycle    : b, g, r, c, m, y, k  # color cycle for plot lines
                                                # as list of string colorspecs:
                                                # single letter, long name, or
                                                # web-style hex
    
    # setting color cycle after calling plt.subplots doesn't "take"
    # try some hex values as **string** colorspecs
    mpl.rcParams['axes.color_cycle'] = ['#129845','#271254', '#FA4411', '#098765', '#000009']
    
    fig, ax2 = plt.subplots(1,1)
    ax2.plot(range(5), ys)
    ax2.set_title('New color cycle')
    
    
    n = 6
    color = plt.cm.coolwarm(np.linspace(0.1,0.9,n)) # This returns RGBA; convert:
    hexcolor = map(lambda rgb:'#%02x%02x%02x' % (rgb[0]*255,rgb[1]*255,rgb[2]*255),
                   tuple(color[:,0:-1]))
    
    mpl.rcParams['axes.color_cycle'] = hexcolor
    
    fig, ax3 = plt.subplots(1,1)
    ax3.plot(range(5), ys)
    ax3.set_title('Color cycle from colormap')
    
    plt.show()
    

    enter image description here enter image description here enter image description here

    0 讨论(0)
  • 2020-11-30 05:49

    For Matplotlib 2.2, using the cycler module will do the trick, without the need to convert to Hex values.

    import cycler
    
    n = 100
    color = pyplot.cm.viridis(np.linspace(0, 1,n))
    mpl.rcParams['axes.prop_cycle'] = cycler.cycler('color', color)
    
    0 讨论(0)
  • 2020-11-30 05:55

    "Continuous" colormap

    If you want to cycle through N colors from a "continous" colormap, like e.g. the default viridis map, the solution by @Gerges works nicely.

    import matplotlib.pyplot as plt
    
    N = 6
    plt.rcParams["axes.prop_cycle"] = plt.cycler("color", plt.cm.viridis(np.linspace(0,1,N)))
    
    fig, ax = plt.subplots()
    for i in range(N):
        ax.plot([0,1], [i, 2*i])
    
    plt.show()
    

    "Discrete" colormap

    Matplotlib provides a few colormap that are "discrete" in the sense that they hold some low number of distinct colors for qualitative visuals, like the tab10 colormap. To cycle through such colormap, the solution might be to not use N but just port all colors of the map to the cycler.

    import matplotlib.pyplot as plt
    
    plt.rcParams["axes.prop_cycle"] = plt.cycler("color", plt.cm.tab20c.colors)
    
    fig, ax = plt.subplots()
    for i in range(15):
        ax.plot([0,1], [i, 2*i])
    
    plt.show()
    

    Note that only ListedColormaps have the .colors attribute, so this only works for those colormap, but not e.g. the jet map.

    Combined solution

    The following is a general purpose function that takes a colormap as input and outputs a corresponding cycler. I originally proposed this solution in this matplotlib issue.

    from matplotlib.pyplot import cycler
    import numpy as np
    from matplotlib.colors import LinearSegmentedColormap, ListedColormap
    import matplotlib.cm
    
    def get_cycle(cmap, N=None, use_index="auto"):
        if isinstance(cmap, str):
            if use_index == "auto":
                if cmap in ['Pastel1', 'Pastel2', 'Paired', 'Accent',
                            'Dark2', 'Set1', 'Set2', 'Set3',
                            'tab10', 'tab20', 'tab20b', 'tab20c']:
                    use_index=True
                else:
                    use_index=False
            cmap = matplotlib.cm.get_cmap(cmap)
        if not N:
            N = cmap.N
        if use_index=="auto":
            if cmap.N > 100:
                use_index=False
            elif isinstance(cmap, LinearSegmentedColormap):
                use_index=False
            elif isinstance(cmap, ListedColormap):
                use_index=True
        if use_index:
            ind = np.arange(int(N)) % cmap.N
            return cycler("color",cmap(ind))
        else:
            colors = cmap(np.linspace(0,1,N))
            return cycler("color",colors)
    

    Usage for the "continuous" case:

    import matplotlib.pyplot as plt
    N = 6
    plt.rcParams["axes.prop_cycle"] = get_cycle("viridis", N)
    
    fig, ax = plt.subplots()
    for i in range(N):
        ax.plot([0,1], [i, 2*i])
    
    plt.show()
    

    Usage for the "discrete" case

    import matplotlib.pyplot as plt
    
    plt.rcParams["axes.prop_cycle"] = get_cycle("tab20c")
    
    fig, ax = plt.subplots()
    for i in range(15):
        ax.plot([0,1], [i, 2*i])
    
    plt.show()
    
    0 讨论(0)
提交回复
热议问题