【问题标题】:Show percent % instead of counts in charts of categorical variables在分类变量图表中显示百分比而不是计数
【发布时间】:2011-04-11 08:44:03
【问题描述】:

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

我正在寻找一种方法让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 如何与单个向量交互。我在挠头,谷歌搜索该错误会给出一个result

【问题讨论】:

  • 数据应该是一个数据框,而不是一个简单的因素。
  • 添加到 hadley 的评论中,使用 mydataf = data.frame(mydataf) 将数据转换为数据框,并将其重命名为 names(mydataf) = foo 即可解决问题

标签: r ggplot2


【解决方案1】:

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

 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

这个问题目前是 google 上“ggplot 计数与百分比直方图”排名第一的问题,因此希望这有助于提取当前在 cmets 中接受的答案的所有信息。

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

【讨论】:

  • 感谢您的回答。关于如何按班级进行操作的任何想法?
  • 正如 .@WAF 建议的那样,此答案不适用于多面数据。请参阅@Erwan 在stackoverflow.com/questions/22181132/… 中的评论
  • 您可能需要在 percent 前面加上它来自的包才能使上述工作(我做到了)。 ggplot(mtcars, aes(x = factor(hp))) + geom_bar(aes(y = (..count..)/sum(..count..))) + scale_y_continuous(labels = scales::percent)
  • 要绕过构面的使用,请改用geom_bar(aes(y = (..count..)/tapply(..count..,..PANEL..,sum)[..PANEL..]))。每个方面的总和应为 100%。
  • 不是用 stat()-command 替换了周围带有“..”的变量吗? ggplot2.tidyverse.org/reference/stat.html
【解决方案2】:

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

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

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

希望这会有所帮助。

【讨论】:

  • 请注意,在 ggplot2 版本 0.9.0 中,formatter 参数将不再起作用。相反,你会想要labels = percent_format())
  • 对于 0.9.0,您需要在使用 percent_format() 之前加载 scales 库,否则它将无法工作。 0.9.0 不再自动加载支持包。
  • ? stat_bin。它显示了ggplot2 向数据框中添加了哪些附加列。所有额外列的格式为..variable..
  • 用简单的aes(y = ..density..) 替换aes(y = (..count..)/sum(..count..)) 有意义吗?从视觉上看,它给出了非常相似(但仍然不同)的图片
  • 在 ggplot 0.9.3.1.0 中,您需要先加载 scales 库,然后使用 scale_y_continuous(labels=percent) 提到的 in the docs
【解决方案3】:

ggplot2 是 2.1.0 版

+ scale_y_continuous(labels = scales::percent)

【讨论】:

    【解决方案4】:

    截至 2017 年 3 月,ggplot2 2.2.1 我认为最佳解决方案已在 Hadley Wickham 的 R for data science 书中进行了解释:

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

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

    【讨论】:

    • 这是截至 2017 年 6 月的最佳答案,适用于按组填充和分面。
    • 由于某种原因,这不允许我使用fill 映射(没有抛出错误,但没有添加填充颜色)。
    • @MaxCandocia 我必须删除 group = 1 才能获得填充映射。也许它有帮助
    • 如果我删除 group 参数,但它不会显示正确的百分比,因为对于每个唯一的 x 值,所有内容都属于其自己的组。
    【解决方案5】:

    如果您希望在 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")
    

    添加条形标签时,您可能希望通过添加到末尾来省略 y 轴以使图表更清晰:

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

    【讨论】:

      【解决方案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~.)
      

      剧情如下:

      【讨论】:

        【解决方案7】:

        由于version 3.3 of ggplot2,我们可以使用方便的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)
        

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

        关于您的 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)
        

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

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

        【讨论】:

          【解决方案8】:

          请注意,如果您的变量是连续的,则必须使用 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..))) 
          

          【讨论】:

          • 很好的解决方案。但是你忘了乘以 100 得到 %,即geom_histogram(aes(y = 100*(..count..)/sum(..count..)))
          【解决方案9】:

          如果你想要百分比 标签 但实际 Ns 在 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)
          

          【讨论】:

            猜你喜欢
            • 2019-03-12
            • 1970-01-01
            • 2015-08-16
            • 1970-01-01
            • 1970-01-01
            • 2015-03-17
            • 2011-03-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多