[英]How to generate random colors in matplotlib?
What's the trivial example of how to generate random colors for passing to plotting functions?如何生成随机颜色以传递给绘图函数的简单示例是什么?
I'm calling scatter inside a loop and want each plot a different color.我在循环内调用 scatter 并希望每个绘图具有不同的颜色。
for X,Y in data:
scatter(X, Y, c=??)
c: a color.
c:一种颜色。 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).
c 可以是单个颜色格式字符串,或长度为 N 的颜色规范序列,或使用通过 kwargs 指定的 cmap 和范数映射到颜色的 N 个数字序列(见下文)。 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 不应是单个数字 RGB 或 RGBA 序列,因为它与要进行颜色映射的值数组无法区分。 c can be a 2-D array in which the rows are RGB or RGBA, however.
然而,c 可以是一个二维数组,其中的行是 RGB 或 RGBA。
I'm calling scatter inside a loop and want each plot in a different color.
我在循环内调用 scatter 并希望每个图都具有不同的颜色。
Based on that, and on your answer: It seems to me that you actually want n
distinct colors for your datasets;基于此以及您的回答:在我看来,您实际上希望数据集有
n
不同的颜色; you want to map the integer indices 0, 1, ..., n-1
to distinct RGB colors.您想将整数索引
0, 1, ..., n-1
映射到不同的 RGB 颜色。 Something like:就像是:
Here is the function to do it:这是执行此操作的函数:
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)
Usage in your pseudo -code snippet in the question:在问题中的伪代码片段中的用法:
cmap = get_cmap(len(data))
for i, (X, Y) in enumerate(data):
scatter(X, Y, c=cmap(i))
I generated the figure in my answer with the following code:我使用以下代码在我的答案中生成了图形:
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()
Tested with both Python 2.7 & matplotlib 1.5, and with Python 3.5 & matplotlib 2.0.使用 Python 2.7 和 matplotlib 1.5 以及 Python 3.5 和 matplotlib 2.0 进行了测试。 It works as expected.
它按预期工作。
for X,Y in data:
scatter(X, Y, c=numpy.random.rand(3,))
elaborating @john-mee 's answer, if you have arbitrarily long data but don't need strictly unique colors:详细说明@john-mee 的答案,如果您有任意长的数据但不需要严格唯一的颜色:
for python 2:对于蟒蛇 2:
from itertools import cycle
cycol = cycle('bgrcmk')
for X,Y in data:
scatter(X, Y, c=cycol.next())
for python 3:对于蟒蛇 3:
from itertools import cycle
cycol = cycle('bgrcmk')
for X,Y in data:
scatter(X, Y, c=next(cycol))
this has the advantage that the colors are easy to control and that it's short.这样做的优点是颜色易于控制并且很短。
For some time I was really annoyed by the fact that matplotlib doesn't generate colormaps with random colors, as this is a common need for segmentation and clustering tasks.有一段时间我真的很恼火,因为 matplotlib 不会生成带有随机颜色的颜色图,因为这是分割和聚类任务的常见需求。
By just generating random colors we may end with some that are too bright or too dark, making visualization difficult.通过只生成随机颜色,我们可能会以一些太亮或太暗的颜色结束,使可视化变得困难。 Also, usually we need the first or last color to be black, representing the background or outliers.
此外,通常我们需要第一个或最后一个颜色为黑色,代表背景或异常值。 So I've wrote a small function for my everyday work
所以我为我的日常工作写了一个小函数
Here's the behavior of it:这是它的行为:
new_cmap = rand_cmap(100, type='bright', first_color_black=True, last_color_black=False, verbose=True)
Than you just use new_cmap as your colormap on matplotlib:比你只使用new_cmap作为 matplotlib 上的颜色图:
ax.scatter(X,Y, c=label, cmap=new_cmap, vmin=0, vmax=num_labels)
The code is here:代码在这里:
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
It's also on github: https://github.com/delestro/rand_cmap它也在 github 上: https : //github.com/delestro/rand_cmap
When less than 9 datasets:当少于 9 个数据集时:
colors = "bgrcmykw"
color_index = 0
for X,Y in data:
scatter(X,Y, c=colors[color_index])
color_index += 1
Since the question is How to generate random colors in matplotlib?
由于问题是
How to generate random colors in matplotlib?
and as I was searching for an answer concerning pie plots
, I think it is worth to put an answer here (for pies
)当我正在寻找有关
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()
Output输出
Here is a more concise version of Ali's answer giving one distinct color per plot :这是 Ali 答案的更简洁版本,每个图给出一种不同的颜色:
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))
Based on Ali's and Champitoad's answer:基于 Ali 和 Champitoad 的回答:
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 being the number of colours you're sampling ^143 是您采样的颜色数
I picked 143 because the entire range of colours on the colormap comes into play here.我选择了 143,因为颜色图上的整个颜色范围都在这里起作用。 What you can do is sample the nth colour every iteration to get the colormap effect.
您可以做的是在每次迭代中对第 n 个颜色进行采样以获得颜色图效果。
n=20 for i,(x,y) in enumerate(points): plt.scatter(x,y,c=cmap(n*i))
Improving the answer https://stackoverflow.com/a/14720445/6654512 to work with Python3.改进答案https://stackoverflow.com/a/14720445/6654512以使用 Python3。 That piece of code would sometimes generate numbers greater than 1 and matplotlib would throw an error.
这段代码有时会生成大于 1 的数字,而 matplotlib 会抛出错误。
for X,Y in data:
scatter(X, Y, c=numpy.random.random(3))
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()
Thanks to @Ali for providing the base implementation.感谢@Ali 提供基本实现。
# 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)
output输出
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.