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

Adding percentage labels in barplots (gglot2)

我有以下数据集,其中包含以下变量,指示一个人是否使用了他们的 phone(虚拟变量 1 = 使用了 phone(“是”)和 0(“否” ) 别的);他们的身份证和他们居住的区和街道。注意同一个人可能在不同的街道下被记录了两次或更多次。但是,我只想统计一次这样的人,即只考虑唯一ID。

district sub_district   id  used_phone
    A   SX  1   Yes
    A   SX  2   Yes
    A   SX  3   No
    A   SX  4   No
    A   SY  4   No
    A   SY  5   Yes
    A   SZ  6   Yes
    A   SX  6   Yes
    A   SZ  7   No
    B   RX  8   No
    B   RV  9   No
    B   RX  9   No
    B   RV  10  Yes
    B   RV  11  Yes
    B   RT  12  Yes
    B   RT  13  Yes
    B   RV  13  Yes
    B   RT  14  No
    B   RX  14  No
  

N.B:used_phone是一个因子变量

对于上述数据集,我想绘制“一个人是否使用了 phone”的分布,为此我使用了以下代码:

  ggplot(df, aes(x=used_phone)) +
  geom_bar(color = "black", fill = "aquamarine4", position = "dodge") +
  labs(x="Used phone", y = "Number of people") +
  ggtitle("Whether person used phone") +
  theme_bw() +
  theme(plot.title = element_text(hjust = 0.5)))
  

这段代码工作正常。但是,我想做两件事:

  1. 在各自的条形图上为每个组(是和否)添加 % 标签,但 y 轴显示“计数”
  2. 绘制图表,使其仅考虑唯一 ID

期待在您的帮助下解决这个问题,因为我是 R 的新手。

谢谢, 拉奇塔

这是一个可行的建议:

  1. 根据 used_phone 总结您的 df,并计算使用过 phone 和未使用过的总人数。
  2. 根据汇总计数,您可以计算百分比份额,然后您可以添加 label 列,它只是带有 % 符号的百分比份额
  3. 您可以使用 ggplot 和新的汇总 df 进行绘图。您可以使用 geom_text() 在条的顶部添加百分比标签,使用 position_stack() 中的 vjust 参数来调整标签的位置。
df %>% 
distinct(.keep_all = T) %>%
  group_by(used_phone) %>% 
  summarize(n()) %>% 
  setNames(., c('used_phone', 'count')) %>% 
  mutate('share' = count/sum(count),
         'label' = paste0(round(share*100, 2), '%')) -> df

  ggplot(df, aes(y=count, x=used_phone)) +
  geom_bar(stat='identity',
           color = "black", 
           fill = "aquamarine4", 
           position = "dodge") +
  geom_text(aes(label = label),
            position = position_stack(vjust = 1.02),
            size = 3) +
  labs(title = 'Whether person used phone',
       x = 'Used Phone',
       y = 'Number of People') +
  theme_bw()

由于 id 中的重复项是同时存在于不同 sub_district 中的 id,并且您不想重复计算它们,所以我删除了变量 sub_district. 然后擦除所有重复项,清点电话并计算百分比。显示了由此产生的 DF。 ggplot 是 geom_col 轴上的百分比是 scales.

我已经注释掉了两行代码,它们允许您在 ggplot 中为地区划分面。由此得出的图表附在底部。

library(tidyverse)

df <- read.table(text="district sub_district   id  used_phone
    A   SX  1   Yes
    A   SX  2   Yes
    A   SX  3   No
    A   SX  4   No
    A   SY  4   No
    A   SY  5   Yes
    A   SZ  6   Yes
    A   SX  6   Yes
    A   SZ  7   No
    B   RX  8   No
    B   RV  9   No
    B   RX  9   No
    B   RV  10  Yes
    B   RV  11  Yes
    B   RT  12  Yes
    B   RT  13  Yes
    B   RV  13  Yes
    B   RT  14  No
    B   RX  14  No", header = T)
table(df$used_phone)
#> 
#>  No Yes 
#>   9  10

ddf <- df %>%
  select(-sub_district) %>%        # delete sub_district
  distinct(id, .keep_all = T) %>%  # unique id`s`
  #group_by(district) %>% 
  count(used_phone) %>%            # cout phones
  mutate(pct = n / sum(n))         # calculate percentage

ddf
#> # A tibble: 2 x 3
#>   used_phone     n   pct
#>   <chr>      <int> <dbl>
#> 1 No             6 0.429
#> 2 Yes            8 0.571

ggplot(ddf, aes(used_phone, pct, fill = used_phone)) +
  geom_col(position = 'dodge') + 
  #facet_wrap(~district) +
  scale_fill_manual(values = c("aquamarine4", "aquamarine3")) +
  scale_y_continuous(labels = scales::percent_format())


基于评论的新增内容:
  • 想要计数的 y 轴
  • 想要百分比作为栏上的标签
  • 想成为地区的分面
ddf <- df %>%
  select(-sub_district) %>%        # delete sub_district
  distinct(id, .keep_all = T) %>%  # unique id`s`
  group_by(district) %>% 
  count(used_phone) %>%            # cout phones
  mutate(pct = n / sum(n),         # calculate percentage
         label = paste0(round(pct*100, 2), '%'))     

ggplot(ddf, aes(used_phone, n, fill = used_phone)) +
  geom_col(position = 'dodge') + 
  facet_wrap(~district) +
  scale_fill_manual(values = c("aquamarine4", "aquamarine3")) +
  geom_text(aes(label = label),
           position = position_stack(vjust = 1.05),
           size = 3) +
  labs(y='count')


*新增* 更改百分比的基础
ddf <- df %>%
  select(-sub_district) %>%        # delete sub_district
  distinct(id, .keep_all = T) %>%  # unique id`s`
  mutate(ssum = n()) %>% 
  group_by(district) %>% 
  count(used_phone, ssum) %>%            # cout phones
  mutate(pct = n / ssum,         # calculate percentage
         label = paste0(round(pct*100, 2), '%'))

我引入了一个新变量,它在分组前对数字求和。这给出了: