R dplyr组内计算相对频率及ggplot分组占比图实现问题
解决方案
问题根源
之前统计和绘图失败的核心原因:宽格式数据转长表后,未按农场类型+物种的维度分组计算出现率,直接调用绘图函数默认按全量样本计数,无法得到分组维度的占比结果。
1. 分组占比统计实现
使用tidyverse套件完成数据整形与分组计算,运行结果完全匹配预期值:
# 加载依赖包 library(tidyverse) # 示例数据 df <- data.frame(id=1:10, farmtype=c(rep("org",4), rep("conv",6)), spA=c(0,0,0,1,1,1,1,1,1,1), spB=c(1,1,1,0,0,0,0,0,0,0) ) # 数据整形+分组统计 df_summarised <- df %>% # 宽表转长表,将两个物种类的列统一规整为species、occur两个字段 pivot_longer(cols = starts_with("sp"), names_to = "species", values_to = "occur") %>% # 按农场类型、物种分组,计算出现占比(0/1变量的均值即为出现率) group_by(farmtype, species) %>% summarise(occur_rate = mean(occur), .groups = "drop")
运行后得到的统计结果:
| farmtype | species | occur_rate |
|---|---|---|
| conv | spA | 1.00 |
| conv | spB | 0.00 |
| org | spA | 0.25 |
| org | spB | 0.75 |
完全符合预期:spA在有机农场占比25%、常规农场100%;spB在有机农场占比75%、常规农场0%。
2. 分组占比柱状图实现
之前的绘图代码存在两个问题:一是未指定y轴映射为出现率,默认geom_bar做全量计数;二是未设置分组柱状图的位置参数,不同农场类型的柱子会堆叠而非并排。直接使用上述汇总好的df_summarised绘图即可,代码如下:
ggplot(df_summarised, aes(x = species, y = occur_rate, fill = farmtype)) + # 绘制并排柱状图 geom_col(width = 0.6, position = position_dodge(width = 0.7)) + # y轴设置为百分比格式,留足标签空间 scale_y_continuous(labels = scales::percent_format(), limits = c(0, 1.1)) + # 在柱子上方添加占比数值标签 geom_text(aes(label = scales::percent(occur_rate, accuracy = 1)), position = position_dodge(width = 0.7), vjust = -0.3, size = 3.5) + # 调整轴标签与主题 labs(x = "物种", y = "物种检出占比", fill = "农场类型") + theme_classic()
如果不想提前做数据汇总,也可以直接在绘图函数内指定统计逻辑,但这种写法对分组参数要求高,容易出现计算错误,不推荐:
# 长表直接绘图写法 df_long <- df %>% pivot_longer(cols = starts_with("sp"), names_to = "species", values_to = "occur") ggplot(df_long, aes(x = species, y = occur, fill = farmtype)) + geom_bar(stat = "summary", fun = "mean", width = 0.6, position = position_dodge(width = 0.7))
内容的提问来源于stack exchange,提问作者Gmichael
相关产品推荐
相关产品推荐

