且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在ggplot2的条形图中添加百分比标签

更新时间:2023-11-26 13:10:04

最简单的方法是在ggplot之外预先计算所需的数量,因为很难跟踪ggplot的计算内容以及这些数量在何处存储和可用. >

首先,汇总您的数据:

 library(dplyr)
library(ggplot2)

mtcars %>% 
    count(cyl = factor(cyl), gear = factor(gear)) %>% 
    mutate(pct = prop.table(n))
#> # A tibble: 8 x 4
#>   cyl   gear      n    pct
#>   <fct> <fct> <int>  <dbl>
#> 1 4     3         1 0.0312
#> 2 4     4         8 0.25  
#> 3 4     5         2 0.0625
#> 4 6     3         2 0.0625
#> 5 6     4         4 0.125 
#> 6 6     5         1 0.0312
#> 7 8     3        12 0.375 
#> 8 8     5         2 0.0625
 

根据需要进行保存,或直接通过管道传输到ggplot中:

 mtcars %>% 
    count(cyl = factor(cyl), gear = factor(gear)) %>% 
    mutate(pct = prop.table(n)) %>% 
    ggplot(aes(x = cyl, y = pct, fill = gear, label = scales::percent(pct))) + 
    geom_col(position = 'dodge') + 
    geom_text(position = position_dodge(width = .9),    # move to center of bars
              vjust = -0.5,    # nudge above top of bar
              size = 3) + 
    scale_y_continuous(labels = scales::percent)
 

如果您真的想将其全部保留在ggplot内部,则可以将geom_textstat = 'count'结合使用(或将stat_countgeom = "text"结合使用,如果愿意):

 ggplot(data = mtcars, aes(x = factor(cyl), 
                          y = prop.table(stat(count)), 
                          fill = factor(gear), 
                          label = scales::percent(prop.table(stat(count))))) +
    geom_bar(position = "dodge") + 
    geom_text(stat = 'count',
              position = position_dodge(.9), 
              vjust = -0.5, 
              size = 3) + 
    scale_y_continuous(labels = scales::percent) + 
    labs(x = 'cyl', y = 'pct', fill = 'gear')
 

它绘制完全相同的东西.

How can I use geom_text to add percentage labels on top of each bar in ggplot2? I know there are several similar questions which are already answered. But they either use only 1 categorical variable or compute the percentages before plotting.
I have following plot:

ggplot(data = mtcars)+
  geom_bar(aes(x = factor(cyl), 
               y = (..count..)/sum(..count..)*100,
               fill = factor(gear)),
           position = "dodge")  

Now I want to add the percentage labels on the top. If I use y = (..count..)/sum(..count..)*100 in geom_text, it says Error in eval(expr, envir, enclos) : object 'count' not found.

It's easiest to calculate the quantities you need beforehand, outside of ggplot, as it's hard to track what ggplot calculates and where those quantities are stored and available.

First, summarize your data:

library(dplyr)
library(ggplot2)

mtcars %>% 
    count(cyl = factor(cyl), gear = factor(gear)) %>% 
    mutate(pct = prop.table(n))
#> # A tibble: 8 x 4
#>   cyl   gear      n    pct
#>   <fct> <fct> <int>  <dbl>
#> 1 4     3         1 0.0312
#> 2 4     4         8 0.25  
#> 3 4     5         2 0.0625
#> 4 6     3         2 0.0625
#> 5 6     4         4 0.125 
#> 6 6     5         1 0.0312
#> 7 8     3        12 0.375 
#> 8 8     5         2 0.0625

Save that if you like, or pipe directly into ggplot:

mtcars %>% 
    count(cyl = factor(cyl), gear = factor(gear)) %>% 
    mutate(pct = prop.table(n)) %>% 
    ggplot(aes(x = cyl, y = pct, fill = gear, label = scales::percent(pct))) + 
    geom_col(position = 'dodge') + 
    geom_text(position = position_dodge(width = .9),    # move to center of bars
              vjust = -0.5,    # nudge above top of bar
              size = 3) + 
    scale_y_continuous(labels = scales::percent)

If you really want to keep it all internal to ggplot, you can use geom_text with stat = 'count' (or stat_count with geom = "text", if you prefer):

ggplot(data = mtcars, aes(x = factor(cyl), 
                          y = prop.table(stat(count)), 
                          fill = factor(gear), 
                          label = scales::percent(prop.table(stat(count))))) +
    geom_bar(position = "dodge") + 
    geom_text(stat = 'count',
              position = position_dodge(.9), 
              vjust = -0.5, 
              size = 3) + 
    scale_y_continuous(labels = scales::percent) + 
    labs(x = 'cyl', y = 'pct', fill = 'gear')

which plots exactly the same thing.