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

基于R语言构建分类学信息的经典环形树状图求助

需求:基于MOTU分类路径构建层级分明的环形树状图

我熟悉R语言,需要构建经典的环形树状图,用于展示宏条形码数据(Multiple Operation Taxonomic Units, MOTUs)的分类路径(如界;门;纲;目;科;属;种)层级关系。

已尝试的方法及问题

我基于metabaR包的ggtaxplot函数逻辑,使用igraph包尝试了两种方法,效果都不理想:

  • 方法一(ggraph实现):外观符合环形树的预期,但所有叶节点被强制放在同一层级,无法展示不同分类级别的差异
  • 方法二(igraph+ggplot实现):分类层级结构正确,但线条呈现网络状,层级关系不够清晰

核心需求

不局限于igraph工具,希望使用ggplot类方法实现,方便后续添加标签、颜色等自定义元素。


测试数据及预处理代码

测试数据

path <- c("root@no rank:Eukaryota@superkingdom:Opisthokonta@clade:Fungi@kingdom:Fungi incertae sedis@no rank:Mucoromycota@phylum:Mortierellomycotina@subphylum:Mortierellomycetes@class:Mortierellales@order:Mortierellaceae@family:Mortierella@genus:unclassified Mortierella@no rank",                                             
          "root@no rank:Eukaryota@superkingdom:Opisthokonta@clade:Fungi@kingdom:Dikarya@subkingdom:Ascomycota@phylum:saccharomyceta@clade:Pezizomycotina@subphylum:leotiomyceta@clade:sordariomyceta@clade:Sordariomycetes@class:Xylariomycetidae@subclass:Xylariales@order:unclassified Xylariales@no rank:Xylariales sp.@species",
          "root@no rank:Eukaryota@superkingdom:Opisthokonta@clade:Fungi@kingdom:Fungi incertae sedis@no rank:Mucoromycota@phylum:Mortierellomycotina@subphylum:Mortierellomycetes@class:Mortierellales@order:Mortierellaceae@family:Linnemannia@genus:Linnemannia zychae@species",                                                   
          "root@no rank:Eukaryota@superkingdom:Opisthokonta@clade:Fungi@kingdom:Fungi incertae sedis@no rank:Mucoromycota@phylum:Mortierellomycotina@subphylum:Mortierellomycetes@class:Mortierellales@order:Mortierellaceae@family",                                                                                                
          "root@no rank:Eukaryota@superkingdom:Opisthokonta@clade:Fungi@kingdom:Dikarya@subkingdom:Ascomycota@phylum:saccharomyceta@clade:Pezizomycotina@subphylum:leotiomyceta@clade:sordariomyceta@clade:Sordariomycetes@class:Hypocreomycetidae@subclass:Hypocreales@order",                                                      
          "root@no rank:Eukaryota@superkingdom:Opisthokonta@clade:Fungi@kingdom:Dikarya@subkingdom:Ascomycota@phylum:saccharomyceta@clade:Pezizomycotina@subphylum:leotiomyceta@clade:sordariomyceta@clade:Leotiomycetes@class:Helotiales@order",                                                                                    
          "root@no rank:Eukaryota@superkingdom:Opisthokonta@clade:Fungi@kingdom:Dikarya@subkingdom:Ascomycota@phylum:saccharomyceta@clade:Pezizomycotina@subphylum:leotiomyceta@clade:dothideomyceta@clade:Dothideomycetes@class:Pleosporomycetidae@subclass:Pleosporales@order",                                                    
          "root@no rank:Eukaryota@superkingdom:Opisthokonta@clade:Fungi@kingdom:Dikarya@subkingdom:Ascomycota@phylum:saccharomyceta@clade:Pezizomycotina@subphylum:leotiomyceta@clade:sordariomyceta@clade:Leotiomycetes@class:Helotiales@order"                                                                                   
)

预处理代码

library(metabaR)
library(magrittr)
library(igraph)
library(ggraph)

# 格式化分类路径信息
sep.level = ":"; sep.info = "@"
parse <- unname(taxoparser(path, sep.level, sep.info)) %>%
  lapply(X =., FUN = function(x){ x <- x[names(x) %in% c("kingdom", "phylum", "class", "order", "family", "genus", "species")]})
path <- sapply(parse, toString) 
parse <- strsplit(path, ", ")
parse.mat <- do.call(rbind, lapply(parse, `length<-`, max(lengths(parse))))

# 构建边列表
edgelist <- NULL
for (i in rev(2:ncol(parse.mat))) {
  idx <- which(!is.na(parse.mat[, i]))
  kid <- parse.mat[idx, i]
  parent <- parse.mat[idx, (i - 1)]
  kidfull <- apply(parse.mat[idx, 1:i, drop = F], 1, toString)
  parentfull <- apply(parse.mat[idx, 1:(i - 1), drop = F], 1, toString)
  
  edgelist <- rbind(
    edgelist,
    unique(cbind(
      parentfull,
      kidfull,
      parent, kid
    ))
  )
}

已尝试的两种方法代码及问题

方法一:ggraph实现

# 第一种尝试:ggraph
mygraph <- graph_from_data_frame( edgelist[,c("parent", "kid")] )
ggraph(mygraph, layout = 'dendrogram', circular = TRUE) +
  geom_edge_elbow() +
  geom_node_point() +
  theme_void()

问题:所有叶节点处于同一层级,无法展示不同分类级别

方法二:igraph+ggplot实现

# 第二种尝试:igraph
g <- igraph::graph.edgelist(edgelist[rev(1:nrow(edgelist)),
                                     c("parentfull", "kidfull")], directed = F)
# 重命名节点
igraph::V(g)$name2 <- ifelse(igraph::V(g)$name %in% edgelist[, "parent"],
                             igraph::V(g)$name,
                             edgelist[match(igraph::V(g)$name, edgelist[, "kidfull"]), "kid"]
)
# 提取节点坐标信息
coords <- layout_as_tree(g, root=1, circular = F, rootlevel = numeric(), mode = "out", flip.y = TRUE)
colnames(coords) <- c("x", "y")
vdf <- data.frame(as.data.frame(get.vertex.attribute(g)), coords)
# 提取边信息
edf <- get.data.frame(g)

edf$from.x <- vdf$x[match(edf$from, as.vector(vdf$name))]
edf$from.y <- vdf$y[match(edf$from, as.vector(vdf$name))]
edf$to.x <- vdf$x[match(edf$to, as.vector(vdf$name))]
edf$to.y <- vdf$y[match(edf$to, as.vector(vdf$name))]

ggplot(data = vdf, aes(x = .data$x, y = -.data$y)) +
  geom_segment(
    data = edf,
    aes(
      x = .data$from.x, xend = .data$to.x,
      y = -.data$from.y, yend = -.data$to.y
    ), size = 0.2, colour = "grey"
  ) +
  geom_point() +
  scale_color_viridis_c() +
  theme_void() + 
  coord_polar() +
  geom_text(aes(label = .data$name2),
            color = "darkgrey", show.legend = FALSE, hjust = 1)

问题:线条呈网络状,层级关系不清晰


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 17:47:31