You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中绘制带时间维度、含单子节点的树状数据?

解决方案

方法1:用igraph + ggraph绘制(推荐,完美支持单子节点)

igraph可直接从边列表构建图,ggraph能灵活控制坐标轴与边长度,适配时间维度需求:

  1. 安装并加载依赖包:
install.packages(c("igraph", "ggraph"))
library(igraph)
library(ggraph)
  1. 构建图对象并添加属性:
# 过滤掉根节点的NA边
tree_edges = tree[!is.na(tree$dt), ]
# 从边列表构建有向图
g = graph_from_data_frame(tree_edges, directed = TRUE, 
                          vertices = data.frame(id = unique(c(tree$i.fr, tree$i.to))))
# 给节点添加时间属性
V(g)$t = tree$t[match(V(g)$id, tree$i.fr)]
# 手动设置根节点时间
V(g)$t[V(g)$id == 0] = 0
  1. 绘制树状图:
ggraph(g, layout = "dendrogram", circular = FALSE) +
  geom_edge_link(aes(length = dt), edge_width = 1, color = "gray50") +
  geom_node_point(aes(x = t), size = 4, color = "darkblue") +
  geom_node_text(aes(x = t, label = id), hjust = -0.3, size = 3.5) +
  scale_x_continuous(name = "时间t", breaks = unique(tree$t)) +
  y_axis(NULL) +
  theme_minimal() +
  theme(panel.grid = element_blank())

该方案会将节点按时间t排列在x轴,边长按dt比例展示,所有单子节点均会保留。

方法2:修复phylo对象后用ggtree绘制

若偏好ggtree,需修正phylo对象的格式问题(ape要求节点编号规则严格):

  1. 重新编号节点:
# 提取所有节点
nodes = unique(c(tree$i.fr, tree$i.to))
# 区分叶子节点(无子节点)和内部节点
leaf_nodes = setdiff(tree$i.to, tree$i.fr)
internal_nodes = setdiff(nodes, leaf_nodes)
# 按ape规则编号:叶子节点从1开始,内部节点从Ntip+1开始
Ntip = length(leaf_nodes)
leaf_map = setNames(seq(Ntip), leaf_nodes)
internal_map = setNames(Ntip + seq_along(internal_nodes), internal_nodes)
full_map = c(leaf_map, internal_map)
  1. 构建合规的phylo对象:
# 生成边矩阵
edge_matrix = cbind(full_map[as.character(tree$i.fr)], full_map[as.character(tree$i.to)])
# 过滤NA的边长度
edge_lengths = tree$dt[!is.na(tree$dt)]
# 构建phylo对象
correct_phylo = list(
  edge = edge_matrix,
  tip.label = as.character(leaf_nodes),
  Nnode = length(internal_nodes),
  edge.length = edge_lengths
)
class(correct_phylo) = "phylo"
  1. 用ggtree绘制时间轴树:
install.packages("ggtree")
library(ggtree)
# 计算每个节点的累计时间
node_times = numeric(length(nodes))
names(node_times) = nodes
node_times["0"] = 0
for (i in seq(nrow(tree))[-1]) {
  node_times[as.character(tree$i.to[i])] = node_times[as.character(tree$i.fr[i])] + tree$dt[i]
}
# 绘制时将x轴映射为节点时间
ggtree(correct_phylo, aes(x = node_times[as.character(node)])) +
  geom_tiplab() +
  geom_nodelab() +
  scale_x_continuous(name = "时间t") +
  theme_tree2()

内容的提问来源于stack exchange,提问作者jessexknight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 05:18:25