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

wis*_*ame 160 r ggplot2

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

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

我正在尝试类似的东西

qplot(mydataf) +
  stat_bin(aes(n = nrow(mydataf), y = ..count../n)) +
  scale_y_continuous(formatter = "percent")
Run Code Online (Sandbox Code Playgroud)

但我必须错误地使用它,因为我有错误.

为了轻松重现设置,这里有一个简化的例子:

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.
Run Code Online (Sandbox Code Playgroud)

在实际情况中,我可能会使用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();
Run Code Online (Sandbox Code Playgroud)

但所有4给出:

Error: ggplot2 doesn't know how to deal with data of class factor
Run Code Online (Sandbox Code Playgroud)

对于简单的情况,会出现相同的错误

ggplot (data=mydataf, aes(levels(mydataf))) +
  geom_bar()
Run Code Online (Sandbox Code Playgroud)

所以它显然是关于如何ggplot与单个载体相互作用的.我正在挠头,谷歌搜索该错误给出了一个结果.

And*_*rew 214

由于回答了这一问题,因此对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)
Run Code Online (Sandbox Code Playgroud)

这是一个可重现的例子,使用mtcars:

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

在此输入图像描述

这个问题目前是google上'ggplot count vs百分比直方图'的第一个问题,所以希望这有助于提取当前所有关于已接受答案的评论中的信息.

备注:如果hp未设置为因子,ggplot将返回:

在此输入图像描述

  • 谢谢你的回答.关于如何在课堂上做这个的任何想法? (11认同)
  • 您可能需要在它所在的包前面加上“percent”前缀才能使上述内容正常工作(我就是这样做的)。`ggplot(mtcars,aes(x = 因子(hp))) + geom_bar(aes(y = (..count..)/sum(..count..))) + scale_y_continuous(标签 = 尺度::百分比) ` (4认同)
  • 要避免使用facet,请使用`geom_bar(aes(y = (..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]))`。每个方面的总和应为 100%。 (4认同)
  • 正如.@ WAF建议的那样,这个答案不适用于分面数据.请参阅@ Erwan在http://stackoverflow.com/questions/22181132/normalizing-y-axis-in-histograms-in-r-ggplot-to-proportion-by-group?lq=1中的评论 (3认同)

Ram*_*ath 58

这个修改过的代码应该可行

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

如果您的数据有NA并且您不希望它们包含在图中,请将na.omit(mydataf)作为参数传递给ggplot.

希望这可以帮助.

  • 请注意,在ggplot2版本0.9.0中,`formatter`参数将不再起作用.相反,你会想要像`labels = percent_format())`这样的东西. (37认同)
  • 使用0.9.0,您需要在使用`percent_format()`之前加载`scales`库,否则它将无效.0.9.0不再自动加载支持包. (25认同)
  • 在ggplot 0.9.3.1.0中,你需要首先加载`scales`库,然后使用'scale_y_continuous(labels = percent)`,如[文档]中所述(http://docs.ggplot2.org/current /scale_continuous.html#) (6认同)

Fab*_*wig 48

使用ggplot2 2.1.0版本

+ scale_y_continuous(labels = scales::percent)
Run Code Online (Sandbox Code Playgroud)


Oli*_* Ma 36

截至2017年3月,凭借ggplot22.2.1,我认为最佳解决方案在Hadley Wickham的R for data science book中有所解释:

ggplot(mydataf) + stat_count(mapping = aes(x=foo, y=..prop.., group=1))
Run Code Online (Sandbox Code Playgroud)

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

  • 这是截至2017年6月的最佳答案,适用于按组填写和分区. (3认同)
  • 出于某种原因,这不允许我使用 `fill` 映射(没有抛出错误,但没有添加填充颜色)。 (2认同)
  • 但是,如果我删除 `group` 参数,它不会显示正确的百分比,因为对于每个唯一的 x 值,所有内容都属于自己的组。 (2认同)

Sam*_*rke 19

如果您想要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")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

添加条形标签时,您可能希望省略y轴以获得更清晰的图表,方法是添加到结尾:

  theme(
        axis.text.y=element_blank(), axis.ticks=element_blank(),
        axis.title.y=element_blank()
  )
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Rti*_*ist 7

请注意,如果您的变量是连续的,则必须使用 geom_histogram(),因为该函数将按“bins”对变量进行分组。

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..))) 
Run Code Online (Sandbox Code Playgroud)


Ste*_*ell 6

如果您想要百分比标签但y轴上的实际Ns,请尝试以下方法:

    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)
Run Code Online (Sandbox Code Playgroud)


ACN*_*CNB 6

这是分面数据的解决方法.(@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~.)
Run Code Online (Sandbox Code Playgroud)

这是情节:

在此输入图像描述


str*_*agu 5

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)
Run Code Online (Sandbox Code Playgroud)

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

关于您的NULL值的一个评论:当您创建向量时,它们会被忽略(即您最终得到一个长度为 9,而不是 11 的向量)。如果您真的想跟踪丢失的数据,则必须NA改用(ggplot2 会将 NA 放在图的右端):

# 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)
Run Code Online (Sandbox Code Playgroud)

reprex 包(v1.0.0)于2021年 2 月 9 日创建

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