如何在 matplotlib 中生成随机颜色?

如何生成随机颜色以传递到绘图函数的简单示例是什么?

我在循环中调用散点,希望每个情节都有不同的颜色。

for X,Y in data:
scatter(X, Y, c=??)

丙: a color. c can be a single color format string, or a sequence of color specifications of length N, or a sequence of N numbers to be mapped to colors using the cmap and norm specified via kwargs (see below). Note that c should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be colormapped. c can be a 2-D array in which the rows are RGB or RGBA, however.

190945 次浏览
for X,Y in data:
scatter(X, Y, c=numpy.random.rand(3,))

当少于9个数据集时:

colors = "bgrcmykw"
color_index = 0


for X,Y in data:
scatter(X,Y, c=colors[color_index])
color_index += 1

我在一个循环中调用散布,并希望每个情节在不同的颜色。

基于这一点,以及您的回答: 在我看来,您实际上需要 n 很明显颜色为您的数据集; 您希望将整数索引 0, 1, ..., n-1映射到不同的 RGB 颜色。类似于:

mapping index to color

下面是这样做的函数:

import matplotlib.pyplot as plt


def get_cmap(n, name='hsv'):
'''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct
RGB color; the keyword argument name must be a standard mpl colormap name.'''
return plt.cm.get_cmap(name, n)

问题中 伪麻黄碱代码片段的用法:

cmap = get_cmap(len(data))
for i, (X, Y) in enumerate(data):
scatter(X, Y, c=cmap(i))

我用以下代码生成了答案中的图形:

import matplotlib.pyplot as plt


def get_cmap(n, name='hsv'):
'''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct
RGB color; the keyword argument name must be a standard mpl colormap name.'''
return plt.cm.get_cmap(name, n)


def main():
N = 30
fig=plt.figure()
ax=fig.add_subplot(111)
plt.axis('scaled')
ax.set_xlim([ 0, N])
ax.set_ylim([-0.5, 0.5])
cmap = get_cmap(N)
for i in range(N):
rect = plt.Rectangle((i, -0.5), 1, 1, facecolor=cmap(i))
ax.add_artist(rect)
ax.set_yticks([])
plt.show()


if __name__=='__main__':
main()

使用 Python 2.7和 matplotlib 1.5以及 Python 3.5和 matplotlib 2.0进行了测试。

详细阐述@john-mee 的答案,如果你有任意长的数据,但不需要严格唯一的颜色:

对于 python 2:

from itertools import cycle
cycol = cycle('bgrcmk')


for X,Y in data:
scatter(X, Y, c=cycol.next())

对于 python 3:

from itertools import cycle
cycol = cycle('bgrcmk')


for X,Y in data:
scatter(X, Y, c=next(cycol))

这样做的好处是颜色容易控制,而且颜色短。

有一段时间,matplotlib 不生成带有随机颜色的彩色地图,因为这是分割和集群任务的常见需求,这让我非常恼火。

通过生成随机的颜色,我们可能会以一些太亮或太暗的颜色结束,这使得视觉化变得困难。此外,通常我们需要的第一个或最后一个颜色是黑色,代表背景或异常值。所以我为我的日常工作写了一个小函数

它的行为是这样的:

new_cmap = rand_cmap(100, type='bright', first_color_black=True, last_color_black=False, verbose=True)

Generated colormap

然后在 matplotlib 上使用 New _ cmap作为颜色图:

ax.scatter(X,Y, c=label, cmap=new_cmap, vmin=0, vmax=num_labels)

密码在这里:

def rand_cmap(nlabels, type='bright', first_color_black=True, last_color_black=False, verbose=True):
"""
Creates a random colormap to be used together with matplotlib. Useful for segmentation tasks
:param nlabels: Number of labels (size of colormap)
:param type: 'bright' for strong colors, 'soft' for pastel colors
:param first_color_black: Option to use first color as black, True or False
:param last_color_black: Option to use last color as black, True or False
:param verbose: Prints the number of labels and shows the colormap. True or False
:return: colormap for matplotlib
"""
from matplotlib.colors import LinearSegmentedColormap
import colorsys
import numpy as np




if type not in ('bright', 'soft'):
print ('Please choose "bright" or "soft" for type')
return


if verbose:
print('Number of labels: ' + str(nlabels))


# Generate color map for bright colors, based on hsv
if type == 'bright':
randHSVcolors = [(np.random.uniform(low=0.0, high=1),
np.random.uniform(low=0.2, high=1),
np.random.uniform(low=0.9, high=1)) for i in xrange(nlabels)]


# Convert HSV list to RGB
randRGBcolors = []
for HSVcolor in randHSVcolors:
randRGBcolors.append(colorsys.hsv_to_rgb(HSVcolor[0], HSVcolor[1], HSVcolor[2]))


if first_color_black:
randRGBcolors[0] = [0, 0, 0]


if last_color_black:
randRGBcolors[-1] = [0, 0, 0]


random_colormap = LinearSegmentedColormap.from_list('new_map', randRGBcolors, N=nlabels)


# Generate soft pastel colors, by limiting the RGB spectrum
if type == 'soft':
low = 0.6
high = 0.95
randRGBcolors = [(np.random.uniform(low=low, high=high),
np.random.uniform(low=low, high=high),
np.random.uniform(low=low, high=high)) for i in xrange(nlabels)]


if first_color_black:
randRGBcolors[0] = [0, 0, 0]


if last_color_black:
randRGBcolors[-1] = [0, 0, 0]
random_colormap = LinearSegmentedColormap.from_list('new_map', randRGBcolors, N=nlabels)


# Display colorbar
if verbose:
from matplotlib import colors, colorbar
from matplotlib import pyplot as plt
fig, ax = plt.subplots(1, 1, figsize=(15, 0.5))


bounds = np.linspace(0, nlabels, nlabels + 1)
norm = colors.BoundaryNorm(bounds, nlabels)


cb = colorbar.ColorbarBase(ax, cmap=random_colormap, norm=norm, spacing='proportional', ticks=None,
boundaries=bounds, format='%1i', orientation=u'horizontal')


return random_colormap

它也在 github 上: https://github.com/delestro/rand_cmap

下面是阿里的回答的一个更简洁的版本,每个情节都有一个不同的颜色:

import matplotlib.pyplot as plt


N = len(data)
cmap = plt.cm.get_cmap("hsv", N+1)
for i in range(N):
X,Y = data[i]
plt.scatter(X, Y, c=cmap(i))

改进答案 https://stackoverflow.com/a/14720445/6654512以使其适用于 Python 3。这段代码有时会生成大于1的数字,matplotlib 会抛出一个错误。

for X,Y in data:
scatter(X, Y, c=numpy.random.random(3))

根据阿里和冠蛤蟆的回答:

If you want to try different palettes for the same, you can do this in a few lines:

cmap=plt.cm.get_cmap(plt.cm.viridis, 143)

就是你要采样的颜色的数量

我选择143是因为颜色图上的所有颜色都在这里起作用。你能做的就是在每次迭代中抽取第 n 个颜色来获得颜色映射效果。

n=20
for i,(x,y) in enumerate(points):
plt.scatter(x, y, c=cmap(n*i))

既然问题是 How to generate random colors in matplotlib?,而且我正在寻找一个关于 pie plots的答案,我认为在这里(对于 pies)给出一个答案是值得的

import numpy as np
from random import sample
import matplotlib.pyplot as plt
import matplotlib.colors as pltc
all_colors = [k for k,v in pltc.cnames.items()]


fracs = np.array([600, 179, 154, 139, 126, 1185])
labels = ["label1", "label2", "label3", "label4", "label5", "label6"]
explode = ((fracs == max(fracs)).astype(int) / 20).tolist()


for val in range(2):
colors = sample(all_colors, len(fracs))
plt.figure(figsize=(8,8))
plt.pie(fracs, labels=labels, autopct='%1.1f%%',
shadow=True, explode=explode, colors=colors)
plt.legend(labels, loc=(1.05, 0.7), shadow=True)
plt.show()

输出

enter image description here

enter image description here

enter code here


import numpy as np


clrs = np.linspace( 0, 1, 18 )  # It will generate
# color only for 18 for more change the number
np.random.shuffle(clrs)
colors = []
for i in range(0, 72, 4):
idx = np.arange( 0, 18, 1 )
np.random.shuffle(idx)
r = clrs[idx[0]]
g = clrs[idx[1]]
b = clrs[idx[2]]
a = clrs[idx[3]]
colors.append([r, g, b, a])

If you want to ensure the colours are distinct - but don't know how many colours are needed. Try something like this. It selects colours from opposite sides of the spectrum and systematically increases granularity.

import math


def calc(val, max = 16):
if val < 1:
return 0
if val == 1:
return max


l = math.floor(math.log2(val-1))    #level
d = max/2**(l+1)                    #devision
n = val-2**l                        #node
return d*(2*n-1)
import matplotlib.pyplot as plt


N = 16
cmap = cmap = plt.cm.get_cmap('gist_rainbow', N)


fig, axs = plt.subplots(2)
for ax in axs:
ax.set_xlim([ 0, N])
ax.set_ylim([-0.5, 0.5])
ax.set_yticks([])


for i in range(0,N+1):
v = int(calc(i, max = N))
rect0 = plt.Rectangle((i, -0.5), 1, 1, facecolor=cmap(i))
rect1 = plt.Rectangle((i, -0.5), 1, 1, facecolor=cmap(v))
axs[0].add_artist(rect0)
axs[1].add_artist(rect1)


plt.xticks(range(0, N), [int(calc(i, N)) for i in range(0, N)])
plt.show()

输出

感谢@Ali 提供了基础实现。

Reproducible results

# generate random colors
colors_ = lambda n: list(map(lambda i: "#" + "%06x" % random.randint(0, 0xFFFFFF),range(n)))


fig = plt.figure()
fig.subplots_adjust(hspace=0.4, wspace=0.4)


# how many random colors to generate?
colors = colors_(6)
for i,color in zip(range(1, 7), colors):
ax = fig.add_subplot(2, 3, i)
ax.text(0.5, 0.5, str((2, 3, i)),
fontsize=18, ha='center', color=color)

输出