根据系统发育信息构建圆形树状图

问题描述 投票:0回答:1

我想构建一个“经典”圆形树状图,例如本文答案中显示的那些https://biology.stackexchange.com/questions/14152/how-should-i-put-a-large -使用 R 进行系统发育到科学论文(我相当习惯 R,但到目前为止我从未做过这样的情节)。

我正在使用环境元条形码数据(多操作分类单位,MOTU)。这些是 DNA 序列,每个序列都被识别到一定的分类水平,并分配给它。我正在考虑构建这样一个图的结果数据是每个 MOTU 的分类“路径”,因此是分类分配的序列,例如界;目;类;科;属;物种(下面的示例)。

我尝试过使用

igraph
包构建此图的不同方法,但都不太令人满意。此代码的大部分基于 ```metabaR`` 包 (
https://github.com/metabaRfactory/metabaR
) 包中的 ggtaxplot 函数。

我认为我可以从这两种方法中得到我想要的东西,但我不确定它们中的任何一种是否真的是有效的方法。非常感谢任何帮助!

我并不完全愿意继续使用 igraph,我可以使用任何其他类似 ggplot 的方法(因为我希望在绘图上添加更多信息,例如标签、颜色)。

非常感谢!

所有这些代码都在 Ubuntu 22.04.2 上的 R 4.2.1 上运行

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"                                                                                  
)

我尝试过使用

igraph
包构建此图的不同方法,但都不太令人满意。此代码的大部分基于 ```metabaR`` 包 (
https://github.com/metabaRfactory/metabaR
) 包中的 ggtaxplot 函数:

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

# Formatting taxonomic information from path
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))))

# Building edgelist
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 :

# first attempt, using ggraph
mygraph <- graph_from_data_frame( edgelist[,c("parent", "kid")] )
ggraph(mygraph, layout = 'dendrogram', circular = TRUE) +
  geom_edge_elbow() +
  geom_node_point() +
  theme_void()

我喜欢这个图的“外观”,但树状图的所有叶子最终都具有相同的 y 值,而我想展示不同的分类级别。

#second attemp, using igraph
g <- igraph::graph.edgelist(edgelist[rev(1:nrow(edgelist)),
                                     c("parentfull", "kidfull")], directed = F)
# Rename nodes with kid names
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"]
)
# extracting info from igraph object
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)
#vdf$angle <- { 90 - as.numeric(rownames(vdf)) * 360 / nrow(vdf)}
# add segments
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)

这里,情节的结构很好,但我不喜欢情节的“网络”外观(曲线),在我看来,这使得层次之间的关系不清楚。

r ggplot2 igraph dendrogram
1个回答
0
投票

我认为你不应该放弃

ggraph
方法。您的主要问题似乎是您的叶节点绘制在错误的深度。然而,在创建绘图布局时,计算节点深度并将其传递给
height
参数是很简单的。为了使图像更清晰一些,我添加了圆圈来指示毒理学水平:

library(tidygraph)

as_tbl_graph(mygraph) %>%
  mutate(depth = node_distance_from(which(node_is_root()))) %>%
  ggraph(layout = 'dendrogram', height = -depth, circular = TRUE) +
  ggforce::geom_circle(aes(x0 = 0, y0 = 0 , r = r), color = 'gray90',
                       data = data.frame(r = seq(0, 1, 1/6))) +
  geom_edge_elbow() +
  geom_node_point() +
  theme_void()

© www.soinside.com 2019 - 2024. All rights reserved.