如何从数据框向堆叠的条形图添加自定义注释? [英] How to add custom annotations, from the dataframe, to a stacked bar chart?

查看:59
本文介绍了如何从数据框向堆叠的条形图添加自定义注释?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在绘制某些类别中各个办公室的交叉列表.我想将一个水平堆积条形图放在一起,其中每个办公室及其价值都被标记.

I'm plotting a cross-tabulation of various offices within certain categories. I'd like to put together a horizontal stacked bar chart where each office and its value is labeled.

下面是一些示例代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# create dataframe
df = pd.DataFrame({'office1': [1, np.nan, np.nan],
                   'office2': [np.nan, 8, np.nan],
                   'office3': [12, np.nan, np.nan],
                   'office4': [np.nan, np.nan, 3],
                   'office5': [np.nan, 5, np.nan],
                   'office6': [np.nan, np.nan, 7],
                   'office7': [3, np.nan, np.nan],
                   'office8': [np.nan, np.nan, 11],
                   'office9': [np.nan, 6, np.nan]},
                  index=['catA', 'catB', 'catC'])

# plot dataframe
ax = df.plot.barh(title="Office Breakdown by Category",
                  legend=False,
                  figsize=(10,7), stacked=True)

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

This gives me a fine starting point:

但是,我想要的是:

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

After some research, I came up with the following code that correctly lines up labels on the 'category' axis:

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)

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

But this doesn't factor in the "stacking" of the bars. I've also tried iterating through the patches container returned by the plot command (which can let me retrieve x & y positions of each rectangle), but I then lose any connection to the office labels.

推荐答案

想通了.如果我遍历数据框每一行的列,我可以构建一个我需要的标签列表,该列表与 ax.patches 中矩形的进展相匹配.解决方法如下:

Figured it out. If I iterate through the columns of each row of the dataframe I can build up a list of the labels I need that matches the progression of the rectangles in ax.patches. Solution below:

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')

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

Which, when added to the code above, yields:

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

Now to just deal with re-arranging labels for bars that are too small.

这篇关于如何从数据框向堆叠的条形图添加自定义注释?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆