我在图表中使用FontAwesome,每个数据点都是 FontAwesome 字体的符号,显示为图标。因此,在图例中,我想使用文本(FontAwesome中的符号)来描述项目。
我使用的代码如下:
from matplotlib.patches import Patch
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
ax = plt.gca()
ax.axis([0, 3, 0, 3])
prop = fm.FontProperties(fname='FontAwesome.otf', size=18)
ax.text(x=0, y=0, s='\uf1c7', color='r', fontproperties=prop)
ax.text(x=2, y=0, s='\uf050', color='g', fontproperties=prop)
plt.legend(handles=[Patch(color='r', label='label1'), Patch(color='g', label='label2')])
所以我想做的是将图例中的颜色条替换为与图中相同的图标。
我使用的句柄是补丁列表。但我发现很难在Patch中添加文本。我发现这里有一个很好的解决方案,可以将图片添加到图例中:Insert image in matplotlib legend
我尝试在该答案中使用 TextArea 替换 BboxImage,但它不起作用,并且 TextArea 不支持像 axis.text 这样的字体属性。
有没有办法可以在图例中使用文本而不是标记?
有关使用
TextArea
的解决方案,请参阅此答案。然后,您需要为 TextArea
内的文本重新创建字体属性。
由于您希望在图例中准确显示作为文本的符号,因此为某些文本对象创建图例处理程序的更简单方法如下,它将文本映射到
TextHandler
。 TextHandler
子类 matplotlib.legend_handler.HandlerBase
及其 create_artists
生成要在图例中显示的文本副本。然后需要针对图例调整一些文本属性。
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerBase
import copy
ax = plt.gca()
ax.axis([-1, 3,-1, 2])
tx1 = ax.text(x=0, y=0, s=ur'$\u2660$', color='r',size=30, ha="right")
tx2 = ax.text(x=2, y=0, s=ur'$\u2665$', color='g',size=30)
class TextHandler(HandlerBase):
def create_artists(self, legend, orig_handle,xdescent, ydescent,
width, height, fontsize,trans):
h = copy.copy(orig_handle)
h.set_position((width/2.,height/2.))
h.set_transform(trans)
h.set_ha("center");h.set_va("center")
fp = orig_handle.get_font_properties().copy()
fp.set_size(fontsize)
# uncomment the following line,
# if legend symbol should have the same size as in the plot
h.set_font_properties(fp)
return [h]
labels = ["label 1", "label 2"]
handles = [tx1,tx2]
handlermap = {type(tx1) : TextHandler()}
ax.legend(handles, labels, handler_map=handlermap,)
plt.show()
另请参阅这个更通用的答案
感谢 ImportanceOfBeingErnest 的回答,我稍微更新了他的解决方案以在图例处理程序中生成文本:
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerBase
import matplotlib.font_manager as fm
from matplotlib.text import Text
class TextLegend(object):
def __init__(self, icon, color, **kwargs):
self.icon = icon
self.color = color
self.kwargs = kwargs
class TextLegendHandler(HandlerBase):
def create_artists(self, legend, orig_handle, xdescent, ydescent,
width, height, fontsize, trans):
x = xdescent + width / 2.0
y = ydescent + height / 2.0
kwargs = {
'horizontalalignment': 'center',
'verticalalignment': 'center',
'color': orig_handle.color,
'fontproperties': fm.FontProperties(fname='FontAwesome.otf', size=fontsize)
}
kwargs.update(orig_handle.kwargs)
annotation = Text(x, y, orig_handle.icon, **kwargs)
return [annotation]
ax = plt.gca()
ax.axis([0, 3, 0, 3])
prop = fm.FontProperties(fname='FontAwesome.otf', size=18)
ax.text(x=0, y=0, s='\uf1c7', color='r', fontproperties=prop)
ax.text(x=2, y=0, s='\uf050', color='g', fontproperties=prop)
plt.legend(
handles=[TextLegend(color='r', icon='\uf1c7'), TextLegend(color='g', icon='\uf050')],
labels=['cat1', 'cat2'],
handler_map={TextLegend: TextLegendHandler()}
)
plt.show()
以下是在没有显式保留句柄列表的情况下代码的样子。在文本中添加
label=
可以完成相同的工作:
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.legend_handler import HandlerBase
import copy
class TextHandler(HandlerBase):
def create_artists(self, legend, orig_handle, xdescent, ydescent,
width, height, fontsize, trans):
h = copy.copy(orig_handle)
h.set_position((width / 2., height / 2.))
h.set_transform(trans)
h.set_ha("center");
h.set_va("center")
fp = orig_handle.get_font_properties().copy()
fp.set_size(fontsize)
# uncomment the following line,
# if legend symbol should have the same size as in the plot
h.set_font_properties(fp)
return [h]
fig, ax = plt.subplots()
bbox = {"boxstyle": "circle", "color": "yellow"}
ax.text(x=0.2, y=0.2, s='\u2665', color='r', size=30, bbox=bbox, label='Hearts')
ax.text(x=0.5, y=0.7, s='\u2660', color='k', size=30, bbox=bbox, label='Spades')
ax.text(x=0.8, y=0.3, s='\u2666', color='b', size=30, bbox=bbox, label='Diamonds')
ax.text(x=0.1, y=0.7, s='\u2663', color='g', size=30, bbox=bbox, label='Clubs')
ax.legend(handler_map={matplotlib.text.Text: TextHandler()})
plt.show()