【问题标题】:Adding percentage labels in barplots (gglot2)在条形图中添加百分比标签 (ggplot2)
【发布时间】:2020-10-12 14:58:19
【问题描述】:

我有以下数据集,其中包含以下变量,指示一个人是否使用过他们的手机(一个虚拟变量,1 = 使用过手机(“是”)和 0(“否”)否则);他们的 ID 和他们居住的区和街道。请注意,同一个人可能在不同街道下被记录两次或多次。但是,我只想统计这样一个人一次,即只考虑唯一 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
  

注意:used_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 新手。

谢谢, 拉奇塔

【问题讨论】:

  • 能否将您的数据的最小子集包含为数据框对象?也许使用 dput(df) 。这允许测试和验证潜在的解决方案。看看minimal reproducible example
  • 感谢彼得的建议!我已经更新了数据集。不幸的是,我无法发布原始数据集,因此制作了一个供您查看。希望这很好。
  • 至于唯一ID,请考虑使用df[!duplicated(df$id),]
  • 嗨,@4redwood:上述链接对我没有帮助。不过,谢谢指出!

标签: r ggplot2 label bar-chart


【解决方案1】:

这是一个可行的建议:

  1. 根据used_phone 总结您的 df 并计算使用过和未使用过手机的总人数。
  2. 根据汇总计数,您可以计算百分比份额,然后您可以添加label cloumn,这只是带有% 符号的百分比
  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()

【讨论】:

  • 原始 DF 有 19 行,used_phone 中的所有行都是 yesno。所以两者的使用率不可能是准确的 50%。而@Rachita 只想计算唯一 ID。
  • 我在用新数据更新问题之前创建了这个答案,感谢您指出不同的情况,我已经修改了代码以包含它。
  • 谢谢!该代码工作正常,除了不同的条件 - 它仍然根据非唯一 ID 计算是/否的数量。我试过你的两个版本。有什么想法可以解决这个问题吗?
【解决方案2】:

由于 id 中的重复项是 id 同时存在于不同的 sub_district 并且您不想重复计算它们,因此我删除了变量 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), '%'))

我引入了一个新变量,它在分组之前将数字相加。这给出了:

【讨论】:

  • 谢谢,MarBlo。但是,我想让我的 y 轴作为“计数”而不是 %。百分比可以作为条形上的标签。你能帮我为地区的平面图做这个吗?
  • @Rachita 我做了一个新的编辑,认为这就是你想要的。 DF 对 2 个区具有相同的值。
  • 是的,我运行它并获得了条形标签!但是,区域内的百分比并不完全正确,因为它们的计算方法是分母 = 区域 A + B 的观察总数。我希望分母是各个区域的观察总数。你能根据这个调整你的代码吗?
  • @Rachita 我有一个额外的编辑。请看一下。
  • 非常感谢,MarBlo!你是救世主。但是,mutate(ssum = n()) %&gt;% 应该在按地区分组之后出现。调整后我得到了它!
猜你喜欢
  • 2021-07-17
  • 2018-06-04
  • 1970-01-01
  • 2022-09-25
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 2021-09-12
相关资源
最近更新 更多