文本部分着色
- 2025-02-11 09:51:00
- admin 原创
- 51
问题描述:
matplotlib 中有没有办法部分指定字符串的颜色?
例子:
plt.ylabel("Today is cloudy.")
我怎样才能将“今天”显示为红色、将“是”显示为绿色并将“多云”显示为蓝色?
解决方案 1:
我只知道如何以非交互方式执行此操作,而且只能使用“PS”后端。
为此,我将使用 Latex 来格式化文本。然后我将包含“颜色”包,并根据需要设置颜色。
下面是一个示例:
import matplotlib
matplotlib.use('ps')
from matplotlib import rc
rc('text',usetex=True)
rc('text.latex', preamble=r'/usepackage{color}')
import matplotlib.pyplot as plt
plt.figure()
plt.ylabel(r' extcolor{red}{Today} '+
r' extcolor{green}{is} '+
r' extcolor{blue}{cloudy.}')
plt.savefig('test.ps')
结果是(使用 ImageMagick 从 ps 转换为 png,因此我可以将其发布在这里):
解决方案 2:
这是交互式版本。编辑:修复了 Matplotlib 3 中产生多余空格的错误。
import matplotlib.pyplot as plt
from matplotlib import transforms
def rainbow_text(x,y,ls,lc,**kw):
"""
Take a list of strings ``ls`` and colors ``lc`` and place them next to each
other, with text ls[i] being shown in color lc[i].
This example shows how to do both vertical and horizontal text, and will
pass all keyword arguments to plt.text, so you can set the font size,
family, etc.
"""
t = plt.gca().transData
fig = plt.gcf()
plt.show()
#horizontal version
for s,c in zip(ls,lc):
text = plt.text(x,y,s+" ",color=c, transform=t, **kw)
text.draw(fig.canvas.get_renderer())
ex = text.get_window_extent()
t = transforms.offset_copy(text._transform, x=ex.width, units='dots')
#vertical version
for s,c in zip(ls,lc):
text = plt.text(x,y,s+" ",color=c, transform=t,
rotation=90,va='bottom',ha='center',**kw)
text.draw(fig.canvas.get_renderer())
ex = text.get_window_extent()
t = transforms.offset_copy(text._transform, y=ex.height, units='dots')
plt.figure()
rainbow_text(0.05,0.05,"all unicorns poop rainbows ! ! !".split(),
['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
size=20)
解决方案 3:
扩展Yann 的答案,LaTeX 着色现在也适用于 PDF 导出:
import matplotlib
from matplotlib.backends.backend_pgf import FigureCanvasPgf
matplotlib.backend_bases.register_backend('pdf', FigureCanvasPgf)
import matplotlib.pyplot as plt
pgf_with_latex = {
"text.usetex": True, # use LaTeX to write all text
"pgf.rcfonts": False, # Ignore Matplotlibrc
"pgf.preamble": [
r'/usepackage{color}' # xcolor for colours
]
}
matplotlib.rcParams.update(pgf_with_latex)
plt.figure()
plt.ylabel(r' extcolor{red}{Today} '+
r' extcolor{green}{is} '+
r' extcolor{blue}{cloudy.}')
plt.savefig("test.pdf")
请注意,此 Python 脚本有时会Undefined control sequence
在第一次尝试时失败并出现错误。再次运行它就会成功。
解决方案 4:
尝试了以上所有方法后,我又回到了我的愚蠢但简单的方法,使用plt.text
。唯一的问题是你需要调整每个单词之间的间距。你可能需要多次调整位置,但我还是喜欢这种方式,因为它
省去了安装 tex 编译器的麻烦,
不需要任何特殊的后端,并且
免除你配置 matplotlib rc 并配置回来的麻烦,否则由于 usetex=True,它可能会减慢你的其他绘图速度
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
label_x = -0.15
ax.text(label_x, 0.35, r"Today", color='red', rotation='vertical', transform=ax.transAxes)
ax.text(label_x, 0.5, r"is", color='green', rotation='vertical', transform=ax.transAxes)
ax.text(label_x, 0.55, r"cloudy", color='blue', rotation='vertical', transform=ax.transAxes)
解决方案 5:
以下内容基于@Paul Ivanov上述的精彩回答;如果这对您有用,请对他的回答点赞。
我稍微修改了他的代码:
处理
ha
(horizontalalignment)关键字参数。使 pdf 输出正常工作(需要在
points
not中工作dots
)。有一个稍微“更好”的 API,用于为几个单词着色。
您可以在下面看到该功能及其使用方法:
import matplotlib.pyplot as plt
from matplotlib import transforms
def multicolored_text(x, y, text, cd, **kw):
"""
Place text at (x, y) with colors for each word specified in the color
dictionary cd, which maps strings to colors, and must include a 'default'
key mapping to the default color.
Based on https://stackoverflow.com/a/9185851/2683, thanks paul ivanov!
"""
fig = plt.gcf()
t = plt.gca().transData
def get_text_width(text, **kw):
temp = plt.text(0, 0, text, **kw)
temp.draw(fig.canvas.get_renderer())
ex = temp.get_window_extent()
# Need the text width in data coordinates, since that's what x uses.
width = t.inverted().transform_bbox(ex).width
temp.remove()
return width
ha = kw.pop('ha', 'left')
match ha:
case 'left':
x = x
case 'center':
x -= get_text_width(text, **kw) / 2
case 'right':
x -= get_text_width(text, **kw)
case _:
raise ValueError(f'invalid value for horizontal alignment {ha}')
for word in text.split(' '):
c = cd.get(word, cd['default'])
text = plt.text(x, y, word + ' ', color=c, transform=t, **kw)
text.draw(fig.canvas.get_renderer())
ex = text.get_window_extent()
# Need the text width in points so that this will work with pdf output.
width = ex.width / fig.dpi * 72 # Can do via fig.dpi_scale_trans?
t = transforms.offset_copy(text._transform, x=width, units='points', fig=fig)
plt.figure()
text = "One does not simply use multicolored text"
colors = {
'default': 'black',
'simply': 'red',
'multicolored': 'blue',
}
multicolored_text(.5, .05, text, colors, ha='center', size=20)
相关推荐
热门文章
项目管理软件有哪些?
热门标签
云禅道AD