如何在分面的geom_density图中添加合并的总密度曲线?
问题描述
我想要绘制甲虫在4个不同区域内停留时间占比的密度图,另有一个包含2个水平的日间时段(Time)分类变量。目前已通过facet_wrap按Habitat分面,并按Time对占比数据分组绘制密度曲线,但为了对比日间时段对占比的影响,希望在每个分面中叠加该Habitat下所有时段的合并占比数据的密度曲线。
当前代码:
Timeserod <- plotsplit$erodius %>% group_by(Time) %>% ungroup() etimesplits <- ggplot(data = Timeserod, aes(x = Proportion, col = Time)) + geom_density() + facet_wrap(~Habitat) etimesplits
我曾考虑使用rbind函数,但不确定如何结合Habitat因子实现。以下是样本数据:
Number Family Time Habitat Proportion 1 erodius Midday Cardboard 0.32 2 erodius Midday Cardboard 0.07 3 erodius Midday Cardboard 0.27 4 erodius Midday Cardboard 0.24 5 erodius Midday Cardboard 0 6 erodius Midday Cardboard 0.05 7 erodius Midday Cardboard 0.46 8 erodius Midday Cardboard 0.06 9 erodius Midday Cardboard 0.23 10 erodius Midday Cardboard 0.44 1 erodius Afternoon Cardboard 0.17 2 erodius Afternoon Cardboard 0.08 3 erodius Afternoon Cardboard 0 4 erodius Afternoon Cardboard 0 5 erodius Afternoon Cardboard 0.14 6 erodius Afternoon Cardboard 0.04 7 erodius Afternoon Cardboard 0.68 8 erodius Afternoon Cardboard 0.11 9 erodius Afternoon Cardboard 0 10 erodius Afternoon Cardboard 0.48 1 erodius Midday Sand 0.23 2 erodius Midday Sand 0 3 erodius Midday Sand 0 4 erodius Midday Sand 0.4 5 erodius Midday Sand 0.01 6 erodius Midday Sand 0.08 7 erodius Midday Sand 0.15 8 erodius Midday Sand 0.29 9 erodius Midday Sand 0.15 10 erodius Midday Sand 0.34 1 erodius Afternoon Sand 0.03 2 erodius Afternoon Sand 0.4 3 erodius Afternoon Sand 0.8 4 erodius Afternoon Sand 0.53 5 erodius Afternoon Sand 0.54 6 erodius Afternoon Sand 0.97 7 erodius Afternoon Sand 0 8 erodius Afternoon Sand 0.57 9 erodius Afternoon Sand 0.56 10 erodius Afternoon Sand 0.18 1 erodius Midday Pine 0.24 2 erodius Midday Pine 0.35 3 erodius Midday Pine 0.97 4 erodius Midday Pine 0.26 5 erodius Midday Pine 0 6 erodius Midday Pine 0.2 7 erodius Midday Pine 0.08 8 erodius Midday Pine 0.54 9 erodius Midday Pine 0.27 10 erodius Midday Pine 0.36 2 erodius Afternoon Pine 0 3 erodius Afternoon Pine 0 4 erodius Afternoon Pine 0.03 5 erodius Afternoon Pine 0 6 erodius Afternoon Pine 0 7 erodius Afternoon Pine 0.42 8 erodius Afternoon Pine 0.08 9 erodius Afternoon Pine 0.01 10 erodius Afternoon Pine 0.28 1 erodius Midday Soil 0 2 erodius Midday Soil 0.65 3 erodius Midday Soil 0 4 erodius Midday Soil 0.23 5 erodius Midday Soil 0 6 erodius Midday Soil 0 7 erodius Midday Soil 0 8 erodius Midday Soil 0 9 erodius Midday Soil 0.58 10 erodius Midday Soil 0.02 1 erodius Afternoon Soil 0 2 erodius Afternoon Soil 0.03 3 erodius Afternoon Soil 0.05 4 erodius Afternoon Soil 0.44 5 erodius Afternoon Soil 0 6 erodius Afternoon Soil 0 7 erodius Afternoon Soil 0 8 erodius Afternoon Soil 0 9 erodius Afternoon Soil 0.04 10 erodius Afternoon Soil 0
解决方案
可以通过构造包含"合并时段"标记的数据集,再叠加一条不区分Time的密度曲线来实现,具体步骤如下:
- 准备合并数据:复制原数据集,将
Time列统一标记为"Total",再和原数据合并,确保每个Habitat下都有对应合并时段的数据。 - 绘制叠加曲线:在原有ggplot代码基础上,新增一个
geom_density层,专门调用合并后的数据,设置独特样式区分。
示例代码:
# 加载依赖包 library(dplyr) library(ggplot2) # 提取原始数据 original_data <- plotsplit$erodius # 构造合并时段数据:复制原数据,将Time替换为"Total" total_data <- original_data %>% mutate(Time = "Total") # 合并原数据与总数据 combined_data <- bind_rows(original_data, total_data) # 绘制密度图 etimesplits <- ggplot(data = combined_data, aes(x = Proportion, col = Time)) + geom_density(linewidth = 0.8) + # 单独设置Total曲线样式:黑色虚线,更突出 geom_density(data = . %>% filter(Time == "Total"), aes(x = Proportion), col = "black", linetype = "dashed", linewidth = 1) + facet_wrap(~Habitat) + # 自定义分组颜色,让Total曲线更显眼 scale_color_manual(values = c("Midday" = "blue", "Afternoon" = "red", "Total" = "black")) + labs(title = "甲虫停留时间占比密度图(按生境分面)", x = "停留时间占比", y = "密度", color = "日间时段") + theme_minimal() etimesplits
代码说明:
bind_rows用于合并原数据和标记为"Total"的数据集,保证每个生境下都包含所有时段的合并数据。- 第二个
geom_density层专门针对合并数据,用黑色虚线突出,便于和两个时段的曲线对比。 scale_color_manual自定义各分组颜色,避免Total曲线和其他时段颜色混淆。
这样每个分面中会同时显示Midday、Afternoon的密度曲线,以及该生境下所有时段合并后的密度曲线,满足对比需求。
内容的提问来源于stack exchange,提问作者FredB
相关产品推荐
相关产品推荐

