在分类变量的图表中显示百分比%而不是计数

我正在绘制一个类别变量,而不是显示每个类别值的计数。

我正在寻找一种方法来让ggplot显示该类别中值的百分比。当然,可以用计算出的百分比创建另一个变量并绘制该变量,但我必须这样做几十次,我希望在一个命令中实现这一点。

我在做一些实验,比如

qplot(mydataf) +
stat_bin(aes(n = nrow(mydataf), y = ..count../n)) +
scale_y_continuous(formatter = "percent")

但我一定是使用不正确,因为我得到了错误。

为了方便地重现设置,这里有一个简化的示例:

mydata <- c ("aa", "bb", NULL, "bb", "cc", "aa", "aa", "aa", "ee", NULL, "cc");
mydataf <- factor(mydata);
qplot (mydataf); #this shows the count, I'm looking to see % displayed.

在实际情况下,我可能会使用ggplot而不是qplot,但使用stat_bin的正确方法仍然让我困惑。

我也尝试了以下四种方法:

ggplot(mydataf, aes(y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent');


ggplot(mydataf, aes(y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent') + geom_bar();


ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent');


ggplot(mydataf, aes(x = levels(mydataf), y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent') + geom_bar();

但所有4个都给予:

Error: ggplot2 doesn't know how to deal with data of class factor

的简单情况也会出现相同的错误

ggplot (data=mydataf, aes(levels(mydataf))) +
geom_bar()

所以它显然是关于ggplot如何与单个向量交互的。我挠头了,谷歌这个错误给出了一个结果

273984 次浏览

修改后的代码应该可以工作

p = ggplot(mydataf, aes(x = foo)) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
scale_y_continuous(formatter = 'percent')

如果你的数据有NAs,而你不希望它们包含在plot中,将na.省略(mydataf)作为参数传递给ggplot。

希望这能有所帮助。

自从回答了这个问题,ggplot语法就有了一些有意义的变化。总结一下上面评论中的讨论:

 require(ggplot2)
require(scales)


p <- ggplot(mydataf, aes(x = foo)) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
## version 3.0.0
scale_y_continuous(labels=percent)

下面是一个使用mtcars的可重复示例:

 ggplot(mtcars, aes(x = factor(hp))) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
scale_y_continuous(labels = percent) ## version 3.0.0

enter image description here

这个问题目前在谷歌上的“ggplot计数vs百分比直方图”中排名第一,所以希望这有助于提取目前在对公认答案的评论中包含的所有信息。

备注:如果hp没有被设置为因子,ggplot返回:

enter image description here

如果你想要百分比标签,但实际的n在y轴上,试试这个:

    library(scales)
perbar=function(xx){
q=ggplot(data=data.frame(xx),aes(x=xx))+
geom_bar(aes(y = (..count..)),fill="orange")
q=q+    geom_text(aes(y = (..count..),label = scales::percent((..count..)/sum(..count..))), stat="bin",colour="darkgreen")
q
}
perbar(mtcars$disp)

如果你想要y轴上的百分比而且标记在条形上:

library(ggplot2)
library(scales)
ggplot(mtcars, aes(x = as.factor(am))) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
geom_text(aes(y = ((..count..)/sum(..count..)), label = scales::percent((..count..)/sum(..count..))), stat = "count", vjust = -0.25) +
scale_y_continuous(labels = percent) +
labs(title = "Manual vs. Automatic Frequency", y = "Percent", x = "Automatic Transmission")

enter image description here

当添加条形标签时,您可能希望省略y轴以使图表更清晰,只需在末尾添加:

  theme(
axis.text.y=element_blank(), axis.ticks=element_blank(),
axis.title.y=element_blank()
)

enter image description here

对于ggplot2 2.1.0版本,就是这样

+ scale_y_continuous(labels = scales::percent)

截至2017年3月,使用ggplot2 2.2.1,我认为最佳解决方案在Hadley Wickham的R for数据科学书籍中得到了解释:

ggplot(mydataf) + stat_count(mapping = aes(x=foo, y=..prop.., group=1))

stat_count计算两个变量:默认使用count,但你可以选择使用显示比例的prop

下面是面向面数据的解决方案。(@Andrew接受的答案在这种情况下不适用。)其思想是使用dplyr计算百分比值,然后使用geom_col创建图形。

library(ggplot2)
library(scales)
library(magrittr)
library(dplyr)


binwidth <- 30


mtcars.stats <- mtcars %>%
group_by(cyl) %>%
mutate(bin = cut(hp, breaks=seq(0,400, binwidth),
labels= seq(0+binwidth,400, binwidth)-(binwidth/2)),
n = n()) %>%
group_by(cyl, bin) %>%
summarise(p = n()/n[1]) %>%
ungroup() %>%
mutate(bin = as.numeric(as.character(bin)))


ggplot(mtcars.stats, aes(x = bin, y= p)) +
geom_col() +
scale_y_continuous(labels = percent) +
facet_grid(cyl~.)

这是情节:

enter image description here

注意,如果你的变量是连续的,你将不得不使用geom_histogram(),因为这个函数将用"bin "对变量进行分组。

df <- data.frame(V1 = rnorm(100))


ggplot(df, aes(x = V1)) +
geom_histogram(aes(y = 100*(..count..)/sum(..count..)))


# if you use geom_bar(), with factor(V1), each value of V1 will be treated as a
# different category. In this case this does not make sense, as the variable is
# really continuous. With the hp variable of the mtcars (see previous answer), it
# worked well since hp was not really continuous (check unique(mtcars$hp)), and one
# can want to see each value of this variable, and not to group it in bins.
ggplot(df, aes(x = factor(V1))) +
geom_bar(aes(y = (..count..)/sum(..count..)))

ggplot2的3.3版本开始,我们可以访问方便的after_stat()函数。

我们可以做一些类似于@Andrew的回答的事情,但不使用..语法:

# original example data
mydata <- c("aa", "bb", NULL, "bb", "cc", "aa", "aa", "aa", "ee", NULL, "cc")


# display percentages
library(ggplot2)
ggplot(mapping = aes(x = mydata,
y = after_stat(count/sum(count)))) +
geom_bar() +
scale_y_continuous(labels = scales::percent)

< img src = " https://i.imgur.com/oBwzDVy.png " alt = " / >

你可以找到所有的“计算变量”;可以在geom_stat_函数的文档中使用。例如,对于geom_bar(),你可以访问countprop变量。(参见计算变量的文档。)

关于NULL值的一个注释:当你创建向量时,它们会被忽略(即你最终得到一个长度为9的向量,而不是11)。如果你真的想跟踪丢失的数据,你将不得不使用NA代替(ggplot2将把NAs放在图的右端):

# use NA instead of NULL
mydata <- c("aa", "bb", NA, "bb", "cc", "aa", "aa", "aa", "ee", NA, "cc")
length(mydata)
#> [1] 11


# display percentages
library(ggplot2)
ggplot(mapping = aes(x = mydata,
y = after_stat(count/sum(count)))) +
geom_bar() +
scale_y_continuous(labels = scales::percent)

< img src = " https://i.imgur.com/XbdOJbj.png " alt = " / >

reprex包 (v1.0.0)创建于2021-02-09

(注意,使用chrfct数据不会对你的例子产生影响。)