使用Matplotlib颜色映射作为颜色循环。

25

如果我通过以下方式创建颜色:

import numpy as np
from matplotlib import pyplot as plt

n = 6
color = plt.cm.coolwarm(np.linspace(0.1,0.9,n))
color

颜色是一个numpy数组:

array([[ 0.34832334,  0.46571115,  0.88834616,  1.        ],
       [ 0.56518158,  0.69943844,  0.99663507,  1.        ],
       [ 0.77737753,  0.84092121,  0.9461493 ,  1.        ],
       [ 0.93577377,  0.8122367 ,  0.74715647,  1.        ],
       [ 0.96049006,  0.61627642,  0.4954666 ,  1.        ],
       [ 0.83936494,  0.32185622,  0.26492398,  1.        ]])

然而,如果我将RGB值(不带透明度值1)作为元组插入到我的.mplstyle文件中(map(tuple,color[:,0:-1])),我会收到与此类似的错误:

in file "/home/moritz/.config/matplotlib/stylelib/ggplot.mplstyle"
    Key axes.color_cycle: [(0.34832334141176474 does not look like a color arg
  (val, error_details, msg))

有什么想法吗?


一个颜色参数应该以(开头,而不是以[(开头,对吗? - cphlewis
仍然不起作用。我尝试了((...), (...)); (...), (...); (...) (...)。 - Moritz
5个回答

37

“连续”色图

如果您想从“连续”的色图中循环使用N种颜色,例如默认的viridis色图,则@Gerges的解决方案非常好用。

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

"离散" 的颜色映射

Matplotlib提供了一些颜色映射,它们在定性视觉方面是“离散”的,例如tab10颜色映射,只保留少量不同的颜色。要循环使用这种颜色映射,解决方法可能是不使用N,而是将映射中的所有颜色都放入循环器中。

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

请注意,只有ListedColormaps具有.colors属性,因此此方法仅适用于这些colormap,而不适用于例如jet地图。

综合解决方案

以下是一个通用函数,它以colormap作为输入并输出相应的cycler。我最初在这个matplotlib问题中提出了这个解决方案。

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)

使用"continuous"情况的方法:

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

"离散"情况的使用方法

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

1
我正在寻找的那行代码是:plt.rcParams["axes.prop_cycle"] = plt.cycler("color", plt.cm.tab20c.colors) - CGFoX
太好了!感谢您提供的综合解决方案! - Helder

35

对于Matplotlib 2.2,使用cycler模块即可实现这一功能,无需将其转换为十六进制值。

import cycler

n = 100
color = pyplot.cm.viridis(np.linspace(0, 1,n))
mpl.rcParams['axes.prop_cycle'] = cycler.cycler('color', color)

请注意,我需要将pyplot.cm更改为plt.cm,将mpl.rcParams更改为plt.rcParams,因为我按照惯例使用了import matplotlib.pyplot as plt - undefined

6
编辑于 2021年4月:自matplotlib 2.2.0版本开始,键axes.color_cycle已被弃用(来源:API更改)。 新方法是使用set_prop_cycle来源:matplotlib.axes.Axes.set_prop_cycle API
实际上,在matplotlibrc中已经有详细的说明:它需要一个字符串表示(十六进制或字母或单词,而不是元组)。
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


2

简述:

如果想要从中获取单个颜色,请使用cmap.colors[INDEX]而不是cmap[INDEX]


以下是如何根据答案创建的步骤:

import matplotlib.pyplot as plt
import matplotlib
import numpy as np

cmap = matplotlib.colors.ListedColormap(matplotlib.cm.get_cmap("Set3").colors[:5])
plt.scatter(np.random.uniform(0, 10, 50), np.random.uniform(0, 10, 50), c=np.random.uniform(0, 10, 50), cmap=cmap)
plt.colorbar()
plt.show()

您可以使用cmap.colors[INDEX]来获取颜色,例如cmap.colors[0]

print(cmap.colors[0])
plt.plot(np.random.uniform(0, 10, 50), color=cmap.colors[0], label=cmap.colors[0])
plt.legend(loc='best')
plt.show()

1
如果您想要本地定义某些内容,在绘图之前可以添加以下代码:
fig, ax4 = plt.subplots(1,1)
ax4.set_prop_cycle(color=plt.cm.plasma(np.linspace(0, 1, n))
ax4.plot(range(5), ys)
ax4.set_title('Color cycle from colormap (local)')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接