Python 如何在seaborn的条形顶部添加百分比?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31749448/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add percentages on top of bars in seaborn?
提问by I am not George
Given the following count plot how do I place percentages on top of the bars?
鉴于以下计数图,我如何在条形图上放置百分比?
import seaborn as sns
sns.set(style="darkgrid")
titanic = sns.load_dataset("titanic")
ax = sns.countplot(x="class", hue="who", data=titanic)
For example for "First" I want total First men/total First, total First women/total First, and total First children/total First on top of their respective bars.
例如,对于“第一”,我想要在他们各自的条形图上的总第一名男性/总第一名、第一名女性总数/总第一名和总第一名儿童/总第一名。
Please let me know if my explanation is not clear.
如果我的解释不清楚,请告诉我。
Thanks!
谢谢!
采纳答案by cphlewis
sns.barplot
doesn't explicitly return the barplot values the way matplotlib.pyplot.bar
does (see last para), but if you've plotted nothing else you can risk assuming that all the patches
in the axes are your values. Then you can use the sub-totals that the barplot function has calculated for you:
sns.barplot
没有像那样明确返回条形图值matplotlib.pyplot.bar
(请参阅最后一段),但是如果您没有绘制其他任何内容,您可能会冒着假设patches
轴中的所有值都是您的值的风险。然后您可以使用 barplot 函数为您计算的小计:
from matplotlib.pyplot import show
import seaborn as sns
sns.set(style="darkgrid")
titanic = sns.load_dataset("titanic")
total = float(len(titanic)) # one person per row
#ax = sns.barplot(x="class", hue="who", data=titanic)
ax = sns.countplot(x="class", hue="who", data=titanic) # for Seaborn version 0.7 and more
for p in ax.patches:
height = p.get_height()
ax.text(p.get_x()+p.get_width()/2.,
height + 3,
'{:1.2f}'.format(height/total),
ha="center")
show()
produces
产生
An alternate approach is to do the sub-summing explicitly, e.g. with the excellent pandas
, and plot with matplotlib
, and also do the styling yourself. (Though you can get quite a lot of styling from sns
context even when using matplotlib
plotting functions. Try it out -- )
另一种方法是明确地进行求和,例如使用优秀的pandas
,并使用 绘图matplotlib
,并自己进行样式设置。(尽管sns
即使使用matplotlib
绘图函数,您也可以从上下文中获得相当多的样式。试试看——)
回答by Lord Zsolt
With the help of cphlewis'ssolution, I managed to put the correct percentages on top of the chart, so the classes sum up to one.
在cphlewis 的解决方案的帮助下,我设法将正确的百分比放在图表的顶部,因此这些类的总和为 1。
for index, category in enumerate(categorical):
plt.subplot(plot_count, 1, index + 1)
order = sorted(data[category].unique())
ax = sns.countplot(category, data=data, hue="churn", order=order)
ax.set_ylabel('')
bars = ax.patches
half = int(len(bars)/2)
left_bars = bars[:half]
right_bars = bars[half:]
for left, right in zip(left_bars, right_bars):
height_l = left.get_height()
height_r = right.get_height()
total = height_l + height_r
ax.text(left.get_x() + left.get_width()/2., height_l + 40, '{0:.0%}'.format(height_l/total), ha="center")
ax.text(right.get_x() + right.get_width()/2., height_r + 40, '{0:.0%}'.format(height_r/total), ha="center")
However, the solution assumes there are 2 options (man, woman) as opposed to 3 (man, woman, child).
但是,该解决方案假设有 2 个选项(男人、女人)而不是 3 个(男人、女人、孩子)。
Since Axes.patches
are ordered in a weird way (first all the blue bars, then all the green bars, then all red bars), you would have to split them and zip them back together accordingly.
由于Axes.patches
以奇怪的方式排序(首先是所有蓝色条,然后是所有绿色条,然后是所有红色条),因此您必须将它们分开并相应地将它们拉回一起。
回答by Deepak Natarajan
with_huefunction will plot percentages on the bar graphs if you have the 'hue' parameter in your plots. It takes the actual graph, feature, Number_of_categories in feature, and hue_categories(number of categories in hue feature) as a parameter.
如果您的图中有“色调”参数,with_hue函数将在条形图上绘制百分比。它以实际图形、特征、特征中的 Number_of_categories 和hue_categories(色调特征中的类别数)作为参数。
without_huefunction will plot percentages on the bar graphs if you have a normal plot. It takes the actual graph and feature as a parameter.
如果您有正常绘图,without_hue函数将在条形图上绘制百分比。它以实际图形和特征为参数。
def with_hue(plot, feature, Number_of_categories, hue_categories):
a = [p.get_height() for p in plot.patches]
patch = [p for p in plot.patches]
for i in range(Number_of_categories):
total = feature.value_counts().values[i]
for j in range(hue_categories):
percentage = '{:.1f}%'.format(100 * a[(j*Number_of_categories + i)]/total)
x = patch[(j*Number_of_categories + i)].get_x() + patch[(j*Number_of_categories + i)].get_width() / 2 - 0.15
y = patch[(j*Number_of_categories + i)].get_y() + patch[(j*Number_of_categories + i)].get_height()
ax.annotate(percentage, (x, y), size = 12)
plt.show()
def without_hue(plot, feature):
total = len(feature)
for p in ax.patches:
percentage = '{:.1f}%'.format(100 * p.get_height()/total)
x = p.get_x() + p.get_width() / 2 - 0.05
y = p.get_y() + p.get_height()
ax.annotate(percentage, (x, y), size = 12)
plt.show()