Python 用图像标注熊猫条形图
我想用“熊猫”注释我创建的水平条形图⭑' 人物。每小节的星星数由评级系统决定,该系统的范围从零到五颗星,并包含半颗星评级。我的问题是没有1/2星文本字符,所以我必须使用包含半星的图像来正确地注释这些条 下面是从我使用的数据帧创建示例的代码:Python 用图像标注熊猫条形图,python,pandas,image,matplotlib,png,Python,Pandas,Image,Matplotlib,Png,我想用“熊猫”注释我创建的水平条形图⭑' 人物。每小节的星星数由评级系统决定,该系统的范围从零到五颗星,并包含半颗星评级。我的问题是没有1/2星文本字符,所以我必须使用包含半星的图像来正确地注释这些条 下面是从我使用的数据帧创建示例的代码: df = pd.DataFrame(index=range(7), data={'Scores': [79.0, 79.5, 81.8, 76.1, 72.8, 87.6, 79.3]}) df['Stars'] = d
df = pd.DataFrame(index=range(7),
data={'Scores': [79.0, 79.5, 81.8, 76.1, 72.8, 87.6, 79.3]})
df['Stars'] = df['Scores'].apply(real_stars)
以下是决定星级的函数:
def real_stars(x):
if x >=88:
return ('★★★★★')
elif x >=83:
return ('★★★★¹/₂')
elif x >=79:
return ('★★★★')
elif x >=75:
return ('★★★¹/₂')
elif x >=71:
return ('★★★')
elif x >=67:
return ('★★¹/₂')
elif x >=63:
return ('★★')
elif x >=59:
return ('★¹/₂')
elif x >=55:
return ('★')
elif x >=50:
return ('¹/₂★')
else:
return None
这是我用来绘制条形图的代码,并用星号标注每个条形图的右侧:
fig = plt.figure(figsize=(7.5,5))
ax = plt.subplot()
plt.box(on=None)
df.plot.barh(ax=ax, width=.75, legend=False)
for i, p in zip(df['Stars'], ax.patches):
width, height = p.get_width(), p.get_height()
x, y = p.get_xy()
ax.annotate(i, (p.get_x()+1*width, p.get_y()+.45*height), fontsize=25,
fontweight='bold', color='white', ha='right', va='center')
我想以完全相同的方式对这些条进行注释,但我不想将半星评级表示为“1/2”,而是希望包含半星的图像。我认为第一步是将图像合并到real_stars函数中,在df['stars']列中显示图像,然后使用该列进行注释
我想使用的图像示例:
在unicode版本11中添加了半星形字符,例如:
import matplotlib.pyplot as plt
import matplotlib.font_manager as mfm
font_path = '<PATH>/Symbola.ttf'
prop = mfm.FontProperties(fname=font_path) # find this font
# Some examples of stars
uni_char = u"\u2605\U0001F7CA\u2BE8\u2BEA"
plt.annotate(uni_char, (0.5, 0.5), fontproperties=prop, fontsize=20)
plt.show()
导入matplotlib.pyplot作为plt
将matplotlib.font\u管理器作为mfm导入
font_path='/Symbola.ttf'
prop=mfm.FontProperties(fname=font\u路径)#查找此字体
#一些星星的例子
uni_char=u“\u2605\U0001F7CA\u2BE8\u2BEA”
plt.annotate(uni_char,(0.5,0.5),fontproperties=prop,fontsize=20)
plt.show()
请参阅,并注意,您必须使用支持此版本中较新标准的字体。上面的示例使用Symbola来注释带有形状的条形图。可以使用
锚定框
,其中包含绘图区域
。绘图区域内的形状是在显示空间中相对于偏移框定义的
import numpy as np
import matplotlib.markers
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from matplotlib.offsetbox import AnchoredOffsetbox, DrawingArea
import matplotlib.pyplot as plt
class AnchoredDrawingArea(AnchoredOffsetbox):
def __init__(self, width, height, xdescent, ydescent,
loc, pad=0.4, borderpad=0.5, **kwargs):
self.da = DrawingArea(width, height, xdescent, ydescent)
super().__init__(loc, pad=pad, borderpad=borderpad,
child=self.da, **kwargs)
def get_star(pos=0, size=10, half=False, **kwargs):
marker = matplotlib.markers.MarkerStyle("*")
p = marker.get_path()
v = np.round(list(p.vertices[:]), 4)
c = np.array(list(p.codes[:]))
v *= size
v[:,0] += pos*2*size
if half:
v = np.delete(v, np.s_[6:-1],0)
c = np.delete(c, np.s_[6:-1],0)
return PathPatch(Path(v, c), **kwargs)
def draw_star(x,y,s, ax, size=10, **kwargs):
# https://matplotlib.org/gallery/misc/anchored_artists.html
ada = AnchoredDrawingArea(np.ceil(s)*2*size-size, size, size/2, size/2, loc="lower center",
bbox_to_anchor=(x,y,0,0), bbox_transform=ax.transData,
frameon=False)
for i in range(int(s)):
star = get_star(i, size=size, **kwargs)
ada.da.add_artist(star)
h = s - int(s)
if h > 0:
star = get_star(int(s), size=size, half=True, **kwargs)
ada.da.add_artist(star)
return ada
def draw_stars(x, y, s, ax=None, size=10, **kwargs):
ax = ax or plt.gca()
for xi,yi,si in zip(x,y,s):
ada = draw_star(xi,yi,si, ax=ax, size=size, **kwargs)
ax.add_artist(ada)
x = np.arange(6)
y = np.array([4,5,3,4,2,4])
stars = np.array([4, 2.5, 1, 3.5, 4.5, 2])
fig, ax = plt.subplots()
ax.bar(x,y)
draw_stars(x,y,stars, ax=ax, size=5, linewidth=0.72,
facecolor="crimson", edgecolor="darkred")
ax.margins(y=0.1)
plt.show()
您看过这个演示吗?谢谢你的回复。我下载了Symbola字体并使用matplotlib.font_管理器创建字体路径,但我无法在jupyter笔记本或导出到excel时正确显示半星。它显示我们就像一个正方形。你有什么进一步的建议,我可以如何让这个工作?再次感谢。