在堆叠的条形图中添加标签

Al *_*l S 3 python matplotlib pandas

我正在绘制某些类别中各个办公室的交叉表。我想放一张水平堆叠的条形图,在其中标记每个办公室及其值。

这是一些示例代码:

df = pd.DataFrame({'office1': pd.Series([1,np.nan,np.nan], index=['catA', 'catB', 'catC']),
              'office2': pd.Series([np.nan,8,np.nan], index=['catA', 'catB', 'catC']),
              'office3': pd.Series([12,np.nan,np.nan], index=['catA', 'catB', 'catC']),
              'office4': pd.Series([np.nan,np.nan,3], index=['catA', 'catB', 'catC']),
              'office5': pd.Series([np.nan,5,np.nan], index=['catA', 'catB', 'catC']),
              'office6': pd.Series([np.nan,np.nan,7], index=['catA', 'catB', 'catC']),
              'office7': pd.Series([3,np.nan,np.nan], index=['catA', 'catB', 'catC']),
              'office8': pd.Series([np.nan,np.nan,11], index=['catA', 'catB', 'catC']),
              'office9': pd.Series([np.nan,6,np.nan], index=['catA', 'catB', 'catC']),
              })
ax = df.plot.barh(title="Office Breakdown by Category", legend=False, figsize=(10,7), stacked=True)
Run Code Online (Sandbox Code Playgroud)

这给了我一个很好的起点:

堆积条形图示例

但是,我想拥有的是: 带标签的条形图

经过研究,我想到了以下代码,可以在“类别”轴上正确排列标签:

def annotateBars(row, ax=ax):
    for col in row.index:
        value = row[col]
        if (str(value) != 'nan'):
            ax.text(value/2, labeltonum(row.name), col+","+str(value))

def labeltonum(label):
    if label == 'catA':
        return 0
    elif label == 'catB':
        return 1
    elif label == 'catC':
        return 2

df.apply(annotateBars, ax=ax, axis=1)
Run Code Online (Sandbox Code Playgroud)

但这不包括条的“堆积”。我还尝试了遍历patchesplot命令返回的容器(可以让我检索每个矩形的x和y位置),但是随后我失去了与办公室标签的任何连接。

Al *_*l S 5

弄清楚了。如果我遍历数据帧每一行的列,则可以建立一个所需标签的列表,这些标签与中矩形的进行匹配ax.patches。解决方案如下:

labels = []
for j in df.columns:
    for i in df.index:
        label = str(j)+": " + str(df.loc[i][j])
        labels.append(label)

patches = ax.patches

for label, rect in zip(labels, patches):
    width = rect.get_width()
    if width > 0:
        x = rect.get_x()
        y = rect.get_y()
        height = rect.get_height()
        ax.text(x + width/2., y + height/2., label, ha='center', va='center')
Run Code Online (Sandbox Code Playgroud)

将其添加到上面的代码后,将产生:

正确注释的条形图

现在只需要处理太小的条形标签...