如何绘制带NA间隙且按组着色的geom_ribbon与geom_line?
问题:在含NA间隙的数据上绘制带分组着色的geom_line和geom_ribbon并保留间隙
问题需求
需要在包含NA间隙的数据上同时绘制geom_line和geom_ribbon,通过分组变量grp为带状图着色,要求线条和带状图在NA位置都保留间隙,不进行插值补全。
示例数据
dat <- tibble(datevar=c(1:10), y_var=c(1:10), y_min=c(1:10)*0.8, y_max=c(1:10)*1.2, grp=c(rep("A", 5), rep("B", 5))) dat[3,2:5] <- NA dat[8,2:5] <- NA dat # A tibble: 10 × 5 datevar y_var y_min y_max grp <int> <int> <dbl> <dbl> <chr> 1 1 1 0.8 1.2 A 2 2 2 1.6 2.4 A 3 3 NA NA NA NA 4 4 4 3.2 4.8 A 5 5 5 4 6 A 6 6 6 4.8 7.2 B 7 7 7 5.6 8.4 B 8 8 NA NA NA NA 9 9 9 7.2 10.8 B 10 10 10 8 12 B
已尝试的方法及问题
geom_line的有效方案:添加
group=1可让线条在NA处保留间隙,代码如下:p <- ggplot(dat) + geom_line(aes(x=datevar, y=y_var, col=grp, group=1)) p线条会在第3、8个位置(NA所在行)断开,同时按
grp分组着色。geom_ribbon的问题:
- 仅设置
fill=grp时,带状图会在NA位置自动插值,无法保留间隙; - 仅设置
group=1时,带状图能保留间隙,但无法按grp分组着色; - 同时设置
fill=grp和group=1时,触发错误:Error in `geom_ribbon()`: ! Problem while converting geom to grob. ℹ Error occurred in the 2nd layer. Caused by error in `draw_group()`: ! Aesthetics can not vary along a ribbon Run `rlang::last_trace()` to see where the error occurred.
- 仅设置
解决方案
核心思路是为每个连续的非NA数据区块创建独立的分组标识,让geom_ribbon按该标识分组绘制,兼顾间隙保留和分组着色需求。
1. 预处理数据,生成连续区块分组
使用dplyr为每个连续的非NA数据生成新的分组变量block_id:
library(dplyr) dat_processed <- dat %>% group_by(grp) %>% mutate(block_id = cumsum(!is.na(grp))) %>% ungroup()
cumsum(!is.na(grp))会在遇到非NA的grp时累加计数,NA行的block_id虽与前一个非NA行相同,但因y_min/y_max为NA,绘图时会自动跳过,从而形成间隙。
2. 绘制图形
使用处理后的数据,geom_line保持group=1,geom_ribbon用block_id作为分组,同时设置fill=grp:
library(ggplot2) ggplot(dat_processed) + geom_ribbon(aes(x=datevar, ymin=y_min, ymax=y_max, fill=grp, group=block_id), alpha=0.3) + geom_line(aes(x=datevar, y=y_var, col=grp, group=1)) + theme_minimal()
效果说明
geom_ribbon按block_id分组绘制,每个连续非NA区块生成独立带状区域,NA位置自然形成间隙;fill=grp正常生效,不同组的带状区域保持对应颜色;geom_line的group=1确保线条在NA处断开,同时按grp着色。
内容的提问来源于stack exchange,提问作者TY Lim
相关产品推荐
相关产品推荐

