我正在使用matplotlib在单个图中绘制20条不同的线。我使用for循环进行绘图,并使用每条线的键标记每条线,然后使用legend函数。
for key in dict.keys():
plot(x,dict[key], label = key)
graph.legend()
但是使用这种方式,图例中会重复很多颜色。有没有办法使用matplotlib确保每条线都分配了唯一的颜色,即使有20多条线?
谢谢
我正在使用matplotlib在单个图中绘制20条不同的线。我使用for循环进行绘图,并使用每条线的键标记每条线,然后使用legend函数。
for key in dict.keys():
plot(x,dict[key], label = key)
graph.legend()
但是使用这种方式,图例中会重复很多颜色。有没有办法使用matplotlib确保每条线都分配了唯一的颜色,即使有20多条线?
谢谢
回答你的问题需要涉及到另外两个SO问题。
回答如何在matplotlib中为每条线选择新颜色?的问题解释了如何定义默认颜色列表并循环选择下一个要绘制的颜色。这可以使用Axes.set_color_cycle
方法完成。
但是,您希望得到正确的颜色列表,最简单的方法是使用颜色映射,正如回答如何从给定的matplotlib颜色映射创建颜色生成器中所解释的那样。在这里,颜色映射将值从0到1映射为一个颜色。
因此,对于您的20条线,您希望在每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_prop_cycle(color=[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()
这是生成的图片:
另一种(更好的,有争议的)解决方案
还有一种使用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_prop_cycle(color=[cm(1.*i/NUM_COLORS) for i in range(NUM_COLORS)])
# new way:
ax.set_prop_cycle(color=[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()
ax.set_color_map()
已被弃用。请改用ax.set_prop_cycle(color=[cm...])
。注意不要更改原意。 - blokeley我有一个包含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()
这是相同的示例,使用不同的线条样式。当然,如果您想要,可以将两者组合在一起。
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()
在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()
除了能够使用seaborn的各种配色方案外,您还可以获得一个RGB元组列表,以备将来需要使用/操作。显然,您可以使用matplotlib的颜色映射算出类似的结果,但我认为这很方便。
clrs = sns.color_palette('muted', n_colors=num_colors) product(['solid', 'dashed', 'dashdot', 'dotted'], clrs)
- Jonasfig, 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))
matplotlib
如此轻松地重复使用颜色对我来说相当疯狂。 - Chris_Rands