Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用图像标注熊猫条形图_Python_Pandas_Image_Matplotlib_Png - Fatal编程技术网

Python 用图像标注熊猫条形图

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

我想用“熊猫”注释我创建的水平条形图⭑' 人物。每小节的星星数由评级系统决定,该系统的范围从零到五颗星,并包含半颗星评级。我的问题是没有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'] = 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时正确显示半星。它显示我们就像一个正方形。你有什么进一步的建议,我可以如何让这个工作?再次感谢。