How to get values above the bars on a seaborn coun

2019-07-25 03:07发布

I have a seaborn count plot, but instead of colour bars I need the value above each bar. My input is pandas data frame.

ax = sns.countplot(x="variable", hue="value", data=pd.melt(dfs))

here dfs has many entries for different columns.

For example, here "man" above the blue bar, "woman" above the brown bar and "child" above the green bar instead of the colour description.

enter image description here

1条回答
神经病院院长
2楼-- · 2019-07-25 03:43

Sometimes it's easier to not try to find ways to tweak seaborn, but rather to directly use matplotlib and build a chart up from scratch.

Here, we can assume to have a dataframe named counts that looks like

hue     c    m    w
class              
A      20   31   29
B      40  112   63
C      85  203  117

where the index are the positions along x axis and the columns are the different hues. In the following, groupedbarplot is a function to take such dataframe as input and plot the bars as groups, and in addition add a label to each one of them.

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(42)

def groupedbarplot(df, width=0.8, annotate="values", ax=None, **kw):
    ax = ax or plt.gca()
    n = len(df.columns)
    w = 1./n
    pos = (np.linspace(w/2., 1-w/2., n)-0.5)*width
    w *= width
    bars = []
    for col, x in zip(df.columns, pos):
        bars.append(ax.bar(np.arange(len(df))+x, df[col].values, width=w, **kw))
        for val, xi in zip(df[col].values, np.arange(len(df))+x):
            if annotate:
                txt = val if annotate == "values" else col
                ax.annotate(txt, xy=(xi, val), xytext=(0,2), 
                            textcoords="offset points",
                            ha="center", va="bottom")
    ax.set_xticks(np.arange(len(df)))
    ax.set_xticklabels(df.index)
    return bars


df = pd.DataFrame({"class" : np.random.choice(list("ABC"), size=700, p=[.1,.3,.6]),
                   "hue" : np.random.choice(["m", "w" ,"c"], size=700, p=[.5,.3,.2])})

counts = df.groupby(["class", "hue"]).size().unstack()

groupedbarplot(counts, annotate="col")
plt.show()

enter image description here

We could also label the values directly, groupedbarplot(counts, annotate="values")

enter image description here

查看更多
登录 后发表回答