ggplot geom_tile绘制热图时如何按条件划掉无效单元格
ggplot2 geom_tile 热图按条件添加单元格划掉标记方案
实现思路
划掉标记的核心是先识别出所有需要标记的单元格(动物出生前、死亡后对应的格子),再通过geom_segment在对应单元格位置绘制交叉斜线,完全贴合热图单元格边界,效果比叠加形状、文本注释更灵活。
判断单元格是否需要标记的规则:
- 单元格对应年份区间的结束年份 < 动物出生年份:属于出生前时段,需要标记
- 动物死亡年份非空,且单元格对应年份区间的起始年份 > 动物死亡年份:属于死亡后时段,需要标记
- 其余时段为动物存活期,保留原热图计数填充
具体实现代码
首先加载依赖包,补全热图数据集的标记字段:
library(tidyverse) # 提取每个动物唯一的出生、死亡基础信息 id_meta <- data %>% distinct(id, birth, death) %>% mutate(y = as.character(id)) # 给热图数据补充年份区间、存活判断标记 heatmap_marked <- heatmap %>% # 匹配每个x轴分类对应的年份起止范围,可根据自己的分段规则调整 mutate( year_min = ifelse(x == "1990-1999", 1990, as.integer(as.character(x))), year_max = ifelse(x == "1990-1999", 1999, as.integer(as.character(x))) ) %>% # 关联动物出生死亡信息 left_join(id_meta, by = "y") %>% # 标记需要划掉的单元格 mutate( need_cross = case_when( year_max < birth ~ TRUE, !is.na(death) & year_min > death ~ TRUE, TRUE ~ FALSE ) )
接下来绘图,在原有geom_tile层之上叠加斜线层:
ggplot(heatmap_marked, aes(x, y, fill = count)) + geom_tile(color = "white") + # 白色单元格边框,提升区分度 # 绘制第一条斜线(左下到右上) geom_segment( data = . %>% filter(need_cross), aes( x = as.numeric(factor(x)) - 0.5, xend = as.numeric(factor(x)) + 0.5, y = as.numeric(factor(y)) - 0.5, yend = as.numeric(factor(y)) + 0.5 ), color = "grey30", linewidth = 0.4 ) + # 绘制第二条斜线(左上到右下),不需要叉号只留单斜线可删除这一层 geom_segment( data = . %>% filter(need_cross), aes( x = as.numeric(factor(x)) - 0.5, xend = as.numeric(factor(x)) + 0.5, y = as.numeric(factor(y)) + 0.5, yend = as.numeric(factor(y)) - 0.5 ), color = "grey30", linewidth = 0.4 ) + # 后续按需自定义配色、主题、轴标签即可 theme_minimal()
调整说明
- 若不需要交叉叉号,仅保留单条斜线划掉效果,删除其中一个
geom_segment层即可 - 斜线的颜色、粗细可通过修改
color、linewidth参数调整,比如需要醒目效果可将颜色改为红色、适当增大线宽 - 若后续调整x轴的年份分段规则,同步修改
year_min、year_max的判断逻辑,保证分段范围匹配即可 - 对于
death字段为NA的存活个体,逻辑会自动仅标记其出生前的单元格,符合需求
内容的提问来源于stack exchange,提问作者burphound
相关产品推荐
相关产品推荐

