使用matplotlib创建超过20种独特的图例颜色

mso*_*ail 46 python matplotlib legend

我正在使用matplotlib在一个图上绘制20条不同的线.我使用for循环绘制并用其键标记每一行,然后使用图例功能

for key in dict.keys():
    plot(x,dict[key], label = key)
graph.legend()
Run Code Online (Sandbox Code Playgroud)

但是使用这种方式,图表在图例中重复了很多颜色.有没有办法确保使用matplotlib和超过20行为每条线分配一个独特的颜色?

谢谢

Yan*_*ann 98

您的问题的答案与另外两个SO问题有关.

如何为matplotlib中的每个绘制线选择一种新颜色的答案解释了如何定义循环的颜色的默认列表,以选择要绘制的下一个颜色.这是通过该Axes.set_color_cycle 方法完成的.

您希望获得正确的颜色列表,这最容易使用颜色映射完成,如此问题的答案中所述:在matplotlib中从给定的颜色映射创建颜色生成器.颜色贴图采用0到1之间的值并返回颜色.

因此,对于20行,您希望以1/20的步长从0循环到1.具体来说,您希望将表单0循环到19/20,因为1映射回0.

这是在这个例子中完成的:

import matplotlib.pyplot as plt
import numpy as np

NUM_COLORS = 20

cm = plt.get_cmap('gist_rainbow')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_color_cycle([cm(1.*i/NUM_COLORS) for i in range(NUM_COLORS)])
for i in range(NUM_COLORS):
    ax.plot(np.arange(10)*(i+1))

fig.savefig('moreColors.png')
plt.show()
Run Code Online (Sandbox Code Playgroud)

这是结果图:

优胜美地山巨人双彩虹1-8-10

另类,更好(有争议)的解决方案

有一种替代方法可以使用ScalarMappable对象将一系列值转换为颜色.此方法的优点是您可以使用非线性Normalization将线索引转换为实际颜色.以下代码生成相同的确切结果:

import matplotlib.pyplot as plt
import matplotlib.cm as mplcm
import matplotlib.colors as colors
import numpy as np

NUM_COLORS = 20

cm = plt.get_cmap('gist_rainbow')
cNorm  = colors.Normalize(vmin=0, vmax=NUM_COLORS-1)
scalarMap = mplcm.ScalarMappable(norm=cNorm, cmap=cm)
fig = plt.figure()
ax = fig.add_subplot(111)
# old way:
#ax.set_color_cycle([cm(1.*i/NUM_COLORS) for i in range(NUM_COLORS)])
# new way:
ax.set_color_cycle([scalarMap.to_rgba(i) for i in range(NUM_COLORS)])
for i in range(NUM_COLORS):
    ax.plot(np.arange(10)*(i+1))

fig.savefig('moreColors.png')
plt.show()
Run Code Online (Sandbox Code Playgroud)

弃用注意
在mplib(1.5+)的更新版本中,该set_color_cycle函数已被弃用,转而使用ax.set_prop_cycle(color=[...]).

  • 在matplotlib v1.5中不推荐使用`ax.set_color_map()`.请改用`ax.set_prop_cycle(color = [cm ...])`. (9认同)
  • 可用的颜色映射列表如下:http://matplotlib.org/examples/color/colormaps_reference.html (2认同)

Don*_*kby 17

我有一个12行的情节,当我尝试Yann的技术时,我发现很难区分具有相似颜色的线条.我的线也成对出现,所以我对每对中的两条线使用相同的颜色,并使用两种不同的线宽.您还可以改变线条样式以获得更多组合.

你可以使用set_prop_cycle(),但我只是在调用后修改了行对象plot().

这是Yann的三个不同线宽的例子:

import matplotlib.pyplot as plt
import numpy as np

NUM_COLORS = 20

cm = plt.get_cmap('gist_rainbow')
fig = plt.figure()
ax = fig.add_subplot(111)
for i in range(NUM_COLORS):
    lines = ax.plot(np.arange(10)*(i+1))
    lines[0].set_color(cm(i//3*3.0/NUM_COLORS))
    lines[0].set_linewidth(i%3 + 1)

fig.savefig('moreColors.png')
plt.show()
Run Code Online (Sandbox Code Playgroud)

带有线宽的示例图

这是具有不同线型的相同示例.当然,如果你愿意,你可以将两者结合起来.

import matplotlib.pyplot as plt
import numpy as np

NUM_COLORS = 20
LINE_STYLES = ['solid', 'dashed', 'dashdot', 'dotted']
NUM_STYLES = len(LINE_STYLES)

cm = plt.get_cmap('gist_rainbow')
fig = plt.figure()
ax = fig.add_subplot(111)
for i in range(NUM_COLORS):
    lines = ax.plot(np.arange(10)*(i+1))
    lines[0].set_color(cm(i//NUM_STYLES*float(NUM_STYLES)/NUM_COLORS))
    lines[0].set_linestyle(LINE_STYLES[i%NUM_STYLES])

fig.savefig('moreColors.png')
plt.show()
Run Code Online (Sandbox Code Playgroud)

带有线型的示例图


Ale*_*oll 11

为了建立Don Kirkby的答案,如果你愿意安装/使用seaborn,那么你可以为你计算颜色:

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

NUM_COLORS = 20
LINE_STYLES = ['solid', 'dashed', 'dashdot', 'dotted']
NUM_STYLES = len(LINE_STYLES)

sns.reset_orig()  # get default matplotlib styles back
clrs = sns.color_palette('husl', n_colors=NUM_COLORS)  # a list of RGB tuples
fig, ax = plt.subplots(1)
for i in range(NUM_COLORS):
    lines = ax.plot(np.arange(10)*(i+1))
    lines[0].set_color(clrs[i])
    lines[0].set_linestyle(LINE_STYLES[i%NUM_STYLES])

fig.savefig('moreColors.png')
plt.show()
Run Code Online (Sandbox Code Playgroud)

除了能够使用seaborn的各种调色板之外,您还可以获得可以在以后使用/操作的RGB元组列表(如果需要).显然,您可以使用matplotlib的色彩图来计算类似的东西,但我觉得这很方便. seaborn husl颜色与20种颜色的地图


GoP*_*kGo 5

这些答案似乎比需要的更复杂。如果您要循环遍历列表来绘制线条,则只需枚举列表并将颜色分配给颜色图上的某个点即可。假设您正在循环访问 pandas 数据框中的所有列:

fig, ax = plt.subplots()
cm = plt.get_cmap('gist_rainbow')
 for count, col in enumerate(df.columns):
    ax.plot(df[col], label = col, linewidth = 2, color = cm(count*20))
Run Code Online (Sandbox Code Playgroud)

这是可行的,因为 cm 只是一个可迭代的颜色数字字典。将它们乘以某个因子可以让您在颜色图中走得更远(颜色差异更大)。