如何在R中堆叠带演化区系着色的系统发育树(类ggdensitree)
解决方案:实现带演化区系颜色的堆叠系统发育树
可以通过提取simmap树的区系分支信息,结合ggtree或ggplot2实现堆叠树的区系着色效果,以下是两种可行方案:
方案1:基于ggplot2的灵活自定义绘制
核心思路是提取每棵树的分支坐标、区系信息,统一整合后用ggplot2绘制层叠树,完全自定义布局:
library(tidyverse) library(ggtree) library(phytools) library(ape) # 1. 批量提取所有树的分支数据(含区系、坐标) tree_data_list <- lapply(seq_along(trees_with_regimes), function(i) { tree <- trees_with_regimes[[i]] # 拆分分支的区系-长度映射 map_df <- tree$maps %>% enframe(name = "edge", value = "regime_length") %>% unnest(regime_length) %>% mutate(regime = names(regime_length), length = as.numeric(regime_length)) %>% select(-regime_length) # 提取分支的节点连接关系 edge_df <- as.data.frame(tree$edge) %>% rename(from = V1, to = V2) %>% mutate(edge = row_number()) # 合并分支关系与区系信息 full_df <- left_join(edge_df, map_df, by = "edge") %>% group_by(edge) %>% mutate(cum_len = cumsum(length), seg_start = tree$edge.length[edge] - cum_len + length, seg_end = tree$edge.length[edge] - cum_len + length + length) %>% ungroup() %>% mutate(tree_id = i) # 获取ggtree的节点坐标布局 layout <- ggtree(tree) %>% ggplot_build() %>% pluck("data", 1) %>% select(node, x, y) # 合并坐标到分支数据,计算区系片段的x轴起止点 full_df <- full_df %>% left_join(layout, by = c("from" = "node")) %>% rename(x_from = x, y_from = y) %>% left_join(layout, by = c("to" = "node")) %>% rename(x_to = x, y_to = y) %>% mutate(x_start = x_from + seg_start, x_end = x_from + seg_end) return(full_df) }) all_tree_data <- bind_rows(tree_data_list) # 2. 绘制堆叠树 tree_spacing <- 1.2 # 树之间的垂直间距 ggplot() + # 绘制带区系颜色的分支片段 geom_segment(data = all_tree_data, aes(x = x_start, xend = x_end, y = y_from + tree_id * tree_spacing, yend = y_to + tree_id * tree_spacing, color = regime), linewidth = 1) + # 绘制节点(可选) geom_point(data = all_tree_data %>% distinct(tree_id, node = from, x = x_from, y = y_from) %>% bind_rows(all_tree_data %>% distinct(tree_id, node = to, x = x_to, y = y_to)), aes(x = x, y = y + tree_id * tree_spacing), size = 1, color = "black") + # 自定义区系颜色 scale_color_manual(values = c("A" = "#2196F3", "B" = "#F44336")) + theme_tree() + labs(color = "演化区系") + ylab("树样本")
方案2:基于ggtree的简洁分面绘制
利用phytools::splitEdge()拆分多区系分支为单一区系短分支,再用ggtree的分面功能实现堆叠:
# 1. 预处理每棵树:拆分多区系分支为单区系分支 trees_processed <- lapply(trees_with_regimes, function(tree) { tree_split <- splitEdge(tree) # 拆分分支 tree_split$edge_regime <- sapply(tree_split$maps, names) # 给分支添加区系属性 return(tree_split) }) # 2. 用ggtree绘制分面堆叠树 ggtree(trees_processed, aes(color = edge_regime)) + facet_wrap(~.id, ncol = 1, strip.position = "right") + scale_color_manual(values = c("A" = "#2196F3", "B" = "#F44336")) + theme_tree2() + labs(color = "演化区系") + theme(strip.text.y = element_text(angle = 0))
关键说明
splitEdge()是phytools的内置函数,能将带有多个演化区系的分支拆分为多个单一区系的短分支,让ggtree可以正确识别每个分支的颜色属性。- 两种方案都能实现和
plotSimmap一致的区系着色效果,方案1适合高度自定义布局,方案2更符合ggtree的使用习惯。 - 颜色可通过
scale_color_manual自由替换,匹配你的需求。
内容的提问来源于stack exchange,提问作者Carlo Meloni
相关产品推荐
相关产品推荐

