我使用matplotlib创建2d线图。出于发布的目的,我希望将这些图分为黑色和白色(不灰度),我正在努力寻找一种非侵入性的解决方案。
Gnuplot会自动改变不同线条的划线模式,与matplotlib类似吗?
答案 0 :(得分:48)
下面我提供了将彩色线条转换为具有独特风格的黑色线条的功能。我的快速测试显示,经过7行,颜色重复。如果情况并非如此(我犯了一个错误),那么在提供的例程中需要对“常量”COLORMAP
进行微调。
以下是例程和示例:
import matplotlib.pyplot as plt
import numpy as np
def setAxLinesBW(ax):
"""
Take each Line2D in the axes, ax, and convert the line style to be
suitable for black and white viewing.
"""
MARKERSIZE = 3
COLORMAP = {
'b': {'marker': None, 'dash': (None,None)},
'g': {'marker': None, 'dash': [5,5]},
'r': {'marker': None, 'dash': [5,3,1,3]},
'c': {'marker': None, 'dash': [1,3]},
'm': {'marker': None, 'dash': [5,2,5,2,5,10]},
'y': {'marker': None, 'dash': [5,3,1,2,1,10]},
'k': {'marker': 'o', 'dash': (None,None)} #[1,2,1,10]}
}
lines_to_adjust = ax.get_lines()
try:
lines_to_adjust += ax.get_legend().get_lines()
except AttributeError:
pass
for line in lines_to_adjust:
origColor = line.get_color()
line.set_color('black')
line.set_dashes(COLORMAP[origColor]['dash'])
line.set_marker(COLORMAP[origColor]['marker'])
line.set_markersize(MARKERSIZE)
def setFigLinesBW(fig):
"""
Take each axes in the figure, and for each line in the axes, make the
line viewable in black and white.
"""
for ax in fig.get_axes():
setAxLinesBW(ax)
xval = np.arange(100)*.01
fig = plt.figure()
ax = fig.add_subplot(211)
ax.plot(xval,np.cos(2*np.pi*xval))
ax.plot(xval,np.cos(3*np.pi*xval))
ax.plot(xval,np.cos(4*np.pi*xval))
ax.plot(xval,np.cos(5*np.pi*xval))
ax.plot(xval,np.cos(6*np.pi*xval))
ax.plot(xval,np.cos(7*np.pi*xval))
ax.plot(xval,np.cos(8*np.pi*xval))
ax = fig.add_subplot(212)
ax.plot(xval,np.cos(2*np.pi*xval))
ax.plot(xval,np.cos(3*np.pi*xval))
ax.plot(xval,np.cos(4*np.pi*xval))
ax.plot(xval,np.cos(5*np.pi*xval))
ax.plot(xval,np.cos(6*np.pi*xval))
ax.plot(xval,np.cos(7*np.pi*xval))
ax.plot(xval,np.cos(8*np.pi*xval))
fig.savefig("colorDemo.png")
setFigLinesBW(fig)
fig.savefig("bwDemo.png")
这提供了以下两个图: 第一个颜色: 然后是黑白的:
您可以调整每种颜色转换为样式的方式。如果您只想使用短划线样式( - 。与 - 相对于您想要的任何模式),请将COLORMAP
对应的'标记'值设置为None
并调整'短划线'模式,反之亦然。
例如,字典中的最后一种颜色是'k'(黑色);最初我只有一个虚线图案[1,2,1,10]
,对应于一个显示的像素,两个没有,一个显示,10个没有,这是一个点 - 点 - 空间图案。然后我评论说,将短划线设置为(无,无),这是一种非常正式的实线说法,并为圆圈添加了标记“o”。
我还设置了一个'常量'MARKERSIZE,它将设置每个标记的大小,因为我发现默认大小有点大。
当您的线条已经有短划线或标记图案时,这显然无法处理,但您可以使用这些例程作为构建更复杂转换器的起点。例如,如果原始绘图有红色实线和红色虚线,它们都会变成带有这些例程的黑色点划线。使用它们时要记住的事情。
答案 1 :(得分:7)
import matplotlib.pyplot as plt
from cycler import cycler
monochrome = (cycler('color', ['k']) * cycler('marker', ['', '.']) *
cycler('linestyle', ['-', '--', ':', '=.']))
plt.rc('axes', prop_cycle=monochrome)
较新的matplotlib
版本引入了新的rcParams
,即axes.prop_cycle
In [1]: import matplotlib.pyplot as plt
In [2]: plt.rcParams['axes.prop_cycle']
Out[2]: cycler('color', ['b', 'g', 'r', 'c', 'm', 'y', 'k'])
对于plt.style.use(...)
或with plt.style.context(...):
提供的固有格式,prop_cycle
相当于传统的,已弃用 axes.color_cycle
In [3]: plt.rcParams['axes.color_cycle']
/.../__init__.py:892: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
warnings.warn(self.msg_depr % (key, alt_key))
Out[3]: ['b', 'g', 'r', 'c', 'm', 'y', 'k']
但cycler
对象有更多可能性,特别是复杂的cycler
可以使用+
和*
从更简单的对象组成,引用不同的属性,分别意为拉链和笛卡尔积。
在这里我们导入cycler
辅助函数,我们定义3个引用不同属性的简单cycler
,最后使用笛卡尔积产生它们
In [4]: from cycler import cycler
In [5]: color_c = cycler('color', ['k'])
In [6]: style_c = cycler('linestyle', ['-', '--', ':', '-.'])
In [7]: markr_c = cycler('marker', ['', '.', 'o'])
In [8]: c_cms = color_c * markr_c * style_c
In [9]: c_csm = color_c * style_c * markr_c
这里我们有两个不同的(?)复杂cycler
,是的,它们是不同的,因为这个操作是非交换的,看看
In [10]: for d in c_csm: print('\t'.join(d[k] for k in d))
- k
- . k
- o k
-- k
-- . k
-- o k
: k
: . k
: o k
-. k
-. . k
-. o k
In [11]: for d in c_cms: print('\t'.join(d[k] for k in d))
- k
-- k
: k
-. k
- . k
-- . k
: . k
-. . k
- o k
-- o k
: o k
-. o k
更快的元素周期是产品中的最后一个,等等,如果我们想要在线条样式中有一定的顺序,这很重要。
如何使用cycler
s的组合?通过plt.rc
或同等方式修改rcParams
的{{1}}。如,
matplotlib
当然这只是一个例子,OP可以混合和匹配不同的属性,以获得最令人愉悦的视觉输出。
答案 2 :(得分:2)
我大量使用了Yann的代码,但今天我从Can i cycle through line styles in matplotlib读了一个答案所以现在我将以这种方式制作我的BW图:
import pylab as plt
from itertools import cycle
lines = ["k-","k--","k-.","k:"]
linecycler = cycle(lines)
plt.figure()
for i in range(4):
x = range(i,i+10)
plt.plot(range(10),x,next(linecycler))
plt.show()
答案 3 :(得分:1)
plot(x,y,'k-.')
之类的内容会产生黑色('k'
)点划线('-.'
)。这不是你想要的吗?