如何绘制不同组分箱值占比图且不堆叠?
实现非堆叠的密度占比图(基线从0开始)
你需要的是将各组的密度占比归一化后,从y=0基线开始绘制而非堆叠,这样能直接对比同一x值下不同组的占比高低。以下是两种可行的实现方法:
方法1:手动预处理数据计算占比
先单独计算每个组的密度,对齐x轴点位后计算各组在每个x点的占比,再用geom_area绘制非堆叠图形:
library(ggplot2) library(dplyr) library(purrr) set.seed(200) df <- data.frame( value = c(rnorm(100, 0, 1), rnorm(100, 0, 2), rnorm(100, 1, 2)), group = rep(c("A", "B", "C"), each = 100) ) # 按组计算密度 density_list <- df %>% split(.$group) %>% map(~density(.$value, n = 200)) # n参数控制x轴采样点数,可按需调整 # 转换为统一格式的数据框 density_df <- map_dfr(density_list, ~data.frame(x = .$x, density = .$y), .id = "group") # 计算每个x点的组占比:当前组密度 / 该x点所有组密度总和 density_df <- density_df %>% group_by(x) %>% mutate(percent = density / sum(density)) %>% ungroup() # 绘制非堆叠面积图 ggplot(density_df, aes(x = x, y = percent, fill = group)) + geom_area(alpha = 0.5, position = "identity") + labs(y = "占比", x = "value", title = "非堆叠密度占比图") + theme_minimal()
方法2:用stat_density直接计算占比
利用ggplot的after_stat函数,在统计密度后直接归一化计算占比,无需提前处理数据:
library(ggplot2) set.seed(200) df <- data.frame( value = c(rnorm(100, 0, 1), rnorm(100, 0, 2), rnorm(100, 1, 2)), group = rep(c("A", "B", "C"), each = 100) ) ggplot(df, aes(x = value, fill = group)) + stat_density( aes(y = after_stat(density / sum(density))), position = "identity", # 关键:关闭堆叠,从0基线绘制 alpha = 0.5, geom = "area" ) + labs(y = "占比", x = "value", title = "非堆叠密度占比图") + theme_minimal()
两种方法的效果一致:每个组的面积/曲线都从y=0开始,同一x值对应的y值就是该组的占比,能直观对比各组在不同x位置的占比高低。
内容的提问来源于stack exchange,提问作者Nikolas
相关产品推荐
相关产品推荐

