Browse code

Document update

Document update

William Lee authored on 22/03/2022 14:46:29
Showing 1 changed files
... ...
@@ -1,11 +1,14 @@
1 1
 ##' drawing phylogenetic trees from list of phylo objects
2
+##' 
3
+##' The trees plotted by 'ggdensitree()' will be stacked on top of each other and the 
4
+##' structures of the trees will be rotated to ensure the consistency of the tip order. 
2 5
 ##'
3 6
 ##' @title ggdensitree
4 7
 ##' @param data a list of phylo objects or any object with an as.phylo and fortify method
5 8
 ##' @param mapping aesthetic mapping
6 9
 ##' @param layout one of 'slanted', 'rectangluar', 'fan', 'circular' or 'radial' (default: 'slanted')
7 10
 ##' @param tip.order the order of the tips by a character vector of taxa names; or an integer, N, to order the tips by the order of the tips in the Nth tree; 'mode' to order the tips by the most common order; 'mds' to order the tips based on MDS of the path length between the tips;  or 'mds_dist' to order the tips based on MDS of the distance between the tips (default: 'mode')
8
-##' @param align.tips TRUE to align trees by their tips and FALSE to align trees by their root (default: TRUE)
11
+##' @param align.tips TRUE (default) to align trees by their tips and FALSE to align trees by their root
9 12
 ##' @param jitter deviation to jitter tips
10 13
 ##' @param ... additional parameters passed to fortify, ggtree and geom_tree
11 14
 ##' @return tree layer
... ...
@@ -13,6 +16,10 @@
13 16
 ##' @importFrom magrittr add
14 17
 ##' @export
15 18
 ##' @author Yu Guangchuang, Bradley R. Jones
19
+##' @references
20
+##' For more detailed demonstration of this function, please refer to chapter 4.4.2 of 
21
+##' *Data Integration, Manipulation and Visualization of Phylogenetic Trees*
22
+##' <http://yulab-smu.top/treedata-book/index.html> by Guangchuang Yu.
16 23
 ##' @examples
17 24
 ##' require(ape)
18 25
 ##' require(dplyr)
Browse code

ggdensitree with align.tips=TRUE sets max x to 0

brad authored on 22/09/2021 22:27:17
Showing 1 changed files
... ...
@@ -119,11 +119,10 @@ ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mo
119 119
 	
120 120
 	## reorder tips (and shift x id align tips)
121 121
 	max.x <- vapply(trees.f, function(x) max(x$x, na.rm = TRUE), numeric(1))
122
-	farthest <- max(max.x)
123 122
 	trees.f <- lapply(1:length(trees), function(i) {
124 123
 		trees.f[[i]]$y <- getYcoord(trees[[i]], tip.order = tip.order)
125 124
 		if (align.tips) {
126
-			trees.f[[i]]$x <- trees.f[[i]]$x + (farthest - max.x[i])
125
+			trees.f[[i]]$x <- trees.f[[i]]$x - max.x[i]
127 126
 		}
128 127
 		if (i > 1 && jitter > 0) {
129 128
 			trees.f[[i]]$y[1:n.tips] %<>% add(stats::rnorm(n.tips, mean=0, sd=jitter))
Browse code

use .data of rlang to avoid NOTE during checking

xiangpin authored on 26/03/2021 11:47:41
Showing 1 changed files
... ...
@@ -62,15 +62,15 @@ ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mo
62 62
 	if (length(tip.order) == 1) {
63 63
 	  if (tip.order == 'mode') {
64 64
 	    first.label <- trees.f[[1]] %>%
65
-	      dplyr::filter(isTip) %>%
66
-	      dplyr::arrange(y) %>%
67
-	      dplyr::pull(label)
65
+	      dplyr::filter(.data$isTip) %>%
66
+	      dplyr::arrange(.data$y) %>%
67
+	      dplyr::pull(.data$label)
68 68
 
69 69
 		  res <- lapply(
70 70
 	      trees.f,
71 71
 	      . %>%
72
-	        dplyr::filter(isTip) %>%
73
-	        dplyr::arrange(y) %>%
72
+	        dplyr::filter(.data$isTip) %>%
73
+	        dplyr::arrange(.data$y) %>%
74 74
 	        dplyr::pull("label") %>%
75 75
 	        match(first.label)
76 76
 	    ) %>%
... ...
@@ -78,8 +78,8 @@ ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mo
78 78
 	      as.data.frame() %>%
79 79
 	      dplyr::group_by_all() %>%
80 80
 	      dplyr::summarize(count = dplyr::n(), .groups = 'drop') %>%
81
-	      dplyr::filter(count == max(count)) %>%
82
-	      dplyr::select(-count) %>%
81
+	      dplyr::filter(.data$count == max(.data$count)) %>%
82
+	      dplyr::select(-.data$count) %>%
83 83
 	      dplyr::slice(1) %>%
84 84
 	      unlist()
85 85
 	    
... ...
@@ -144,4 +144,4 @@ cophenetic.phylo.check.length <- function(tree, method) {
144 144
 		tree$edge.length <- rep(1, nrow(tree$edge))
145 145
 	
146 146
 	stats::cophenetic(tree)
147
-}
148 147
\ No newline at end of file
148
+}
Browse code

changed `$` to pull

brad authored on 18/03/2021 06:20:21
Showing 1 changed files
... ...
@@ -71,7 +71,7 @@ ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mo
71 71
 	      . %>%
72 72
 	        dplyr::filter(isTip) %>%
73 73
 	        dplyr::arrange(y) %>%
74
-	        `$`("label") %>%
74
+	        dplyr::pull("label") %>%
75 75
 	        match(first.label)
76 76
 	    ) %>%
77 77
 	      do.call(rbind, .) %>%
Browse code

added new default tip.order to ggdensitree that is more similar to DensiTree's default tip order

brad authored on 17/03/2021 22:18:43
Showing 1 changed files
... ...
@@ -4,7 +4,7 @@
4 4
 ##' @param data a list of phylo objects or any object with an as.phylo and fortify method
5 5
 ##' @param mapping aesthetic mapping
6 6
 ##' @param layout one of 'slanted', 'rectangluar', 'fan', 'circular' or 'radial' (default: 'slanted')
7
-##' @param tip.order the order of the tips by a character vector of taxa names; or an integer, N, to order the tips by the order of the tips in the Nth tree; 'mds' to order the tips based on MDS of the path length between the tips;  or 'mds_dist' to order the tips based on MDS of the distance between the tips (default: 'mds_dist')
7
+##' @param tip.order the order of the tips by a character vector of taxa names; or an integer, N, to order the tips by the order of the tips in the Nth tree; 'mode' to order the tips by the most common order; 'mds' to order the tips based on MDS of the path length between the tips;  or 'mds_dist' to order the tips based on MDS of the distance between the tips (default: 'mode')
8 8
 ##' @param align.tips TRUE to align trees by their tips and FALSE to align trees by their root (default: TRUE)
9 9
 ##' @param jitter deviation to jitter tips
10 10
 ##' @param ... additional parameters passed to fortify, ggtree and geom_tree
... ...
@@ -16,41 +16,42 @@
16 16
 ##' @examples
17 17
 ##' require(ape)
18 18
 ##' require(dplyr)
19
+##' require(tidyr)
19 20
 ##' 
20
-##' # Plot mutliple trees with aligned tips
21
+##' # Plot multiple trees with aligned tips
21 22
 ##' trees <- list(read.tree(text="((a:1,b:1):1.5,c:2.5);"), read.tree(text="((a:1,c:1):1,b:2);"));
22 23
 ##' ggdensitree(trees) + geom_tiplab()
23 24
 ##' 
24
-##' # Plot multiple trees with aligmned tips with tip labls and separate tree colors
25
+##' # Plot multiple trees with aligned tips with tip labels and separate tree colors
25 26
 ##' trees.fort <- list(trees[[1]] %>% fortify %>% mutate(tree="a"), trees[[2]] %>% fortify %>% mutate(tree="b"));
26 27
 ##' ggdensitree(trees.fort, aes(colour=tree)) + geom_tiplab(colour='black')
27 28
 ##' 
28 29
 ##' 
29 30
 ##' # Generate example data
30 31
 ##' set.seed(1)
31
-##' trees <- rmtree(5, 10)
32
-##' time.trees <- lapply(1:length(trees), function(i) {
33
-##'  	tree <- trees[[i]]
32
+##' random.trees <- rmtree(5, 10)
33
+##' time.trees <- lapply(seq_along(random.trees), function(i) {
34
+##'  	tree <- random.trees[[i]]
34 35
 ##'  	tree$tip.label <- paste0("t", 1:10)
35 36
 ##' 	dates <- estimate.dates(tree, 1:10, mu=1, nsteps=1)
36 37
 ##' 	tree$edge.length <- dates[tree$edge[, 2]] - dates[tree$edge[, 1]]
37 38
 ##' 	fortify(tree) %>% mutate(tree=factor(i, levels=as.character(1:10)))
38 39
 ##' })
39 40
 ##' 
40
-##' # Plot multiple trees with aligned tips from muliple time points
41
+##' # Plot multiple trees with aligned tips from multiple time points
41 42
 ##' ggdensitree(time.trees, aes(colour=tree), tip.order=paste0("t", 1:10)) + geom_tiplab(colour='black')
42 43
 ##' 
43 44
 ##' 
44 45
 ##' # Read example data
45
-##' trees <- read.tree(system.file("examples", "ggdensitree_example.tree", package="ggtree"))
46
+##' example.trees <- read.tree(system.file("examples", "ggdensitree_example.tree", package="ggtree"))
46 47
 ##' 
47 48
 ##' # Compute OTU
48 49
 ##' grp <- list(A = c("a.t1", "a.t2", "a.t3", "a.t4"), B = c("b.t1", "b.t2", "b.t3", "b.t4"), C = c("c.t1", "c.t2", "c.t3", "c.t4"))
49
-##' trees <- lapply(trees, groupOTU, grp)
50
+##' otu.trees <- lapply(example.trees, groupOTU, grp)
50 51
 ##' 
51 52
 ##' # Plot multiple trees colored by OTU
52
-##' ggdensitree(trees, aes(colour=group), alpha=1/6) + scale_colour_manual(values=c("black", "red", "green", "blue"))
53
-ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mds_dist',
53
+##' ggdensitree(otu.trees, aes(colour=group), alpha=1/6, tip.order='mds') + scale_colour_manual(values=c("black", "red", "green", "blue"))
54
+ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mode',
54 55
 						align.tips=TRUE, jitter=0, ...) {
55 56
 	## factorize to simplify code
56 57
 	trees <- lapply(data, as.phylo)
... ...
@@ -59,7 +60,31 @@ ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='md
59 60
 	
60 61
 	## determine tip order
61 62
 	if (length(tip.order) == 1) {
62
-		if (grepl('mds', tip.order)) {
63
+	  if (tip.order == 'mode') {
64
+	    first.label <- trees.f[[1]] %>%
65
+	      dplyr::filter(isTip) %>%
66
+	      dplyr::arrange(y) %>%
67
+	      dplyr::pull(label)
68
+
69
+		  res <- lapply(
70
+	      trees.f,
71
+	      . %>%
72
+	        dplyr::filter(isTip) %>%
73
+	        dplyr::arrange(y) %>%
74
+	        `$`("label") %>%
75
+	        match(first.label)
76
+	    ) %>%
77
+	      do.call(rbind, .) %>%
78
+	      as.data.frame() %>%
79
+	      dplyr::group_by_all() %>%
80
+	      dplyr::summarize(count = dplyr::n(), .groups = 'drop') %>%
81
+	      dplyr::filter(count == max(count)) %>%
82
+	      dplyr::select(-count) %>%
83
+	      dplyr::slice(1) %>%
84
+	      unlist()
85
+	    
86
+	    tip.order <- first.label[res]
87
+		} else if (grepl('mds', tip.order)) {
63 88
 			method <- tip.order
64 89
 			
65 90
 			first.label <- trees.f[[1]] %>%
Browse code

merged; fixed example; changed Brad Jones email

brj1 authored on 06/12/2019 22:27:49
Showing 0 changed files
Browse code

added example to ggdensitree andnew example file

brj1 authored on 06/12/2019 21:48:17
Showing 1 changed files
... ...
@@ -4,7 +4,7 @@
4 4
 ##' @param data a list of phylo objects or any object with an as.phylo and fortify method
5 5
 ##' @param mapping aesthetic mapping
6 6
 ##' @param layout one of 'slanted', 'rectangluar', 'fan', 'circular' or 'radial' (default: 'slanted')
7
-##' @param tip.order the order of the tips by a character vector of taxa names; or an integer, N, to order the tips by the order of the tips in the Nth tree; or 'mds' to order the tips based on MDS of the distance between the tips (default: 'mds')
7
+##' @param tip.order the order of the tips by a character vector of taxa names; or an integer, N, to order the tips by the order of the tips in the Nth tree; 'mds' to order the tips based on MDS of the path length between the tips;  or 'mds_dist' to order the tips based on MDS of the distance between the tips (default: 'mds')
8 8
 ##' @param align.tips TRUE to align trees by their tips and FALSE to align trees by their root (default: TRUE)
9 9
 ##' @param jitter deviation to jitter tips
10 10
 ##' @param ... additional parameters passed to fortify, ggtree and geom_tree
... ...
@@ -17,12 +17,16 @@
17 17
 ##' require(ape)
18 18
 ##' require(dplyr)
19 19
 ##' 
20
+##' # Plot mutliple trees with aligned tips
20 21
 ##' trees <- list(read.tree(text="((a:1,b:1):1.5,c:2.5);"), read.tree(text="((a:1,c:1):1,b:2);"));
21 22
 ##' ggdensitree(trees) + geom_tiplab()
22 23
 ##' 
24
+##' # Plot multiple trees with aligmned tips with tip labls and separate tree colors
23 25
 ##' trees.fort <- list(trees[[1]] %>% fortify %>% mutate(tree="a"), trees[[2]] %>% fortify %>% mutate(tree="b"));
24 26
 ##' ggdensitree(trees.fort, aes(colour=tree)) + geom_tiplab(colour='black')
25 27
 ##' 
28
+##' 
29
+##' # Generate example data
26 30
 ##' set.seed(1)
27 31
 ##' trees <- rmtree(5, 10)
28 32
 ##' time.trees <- lapply(1:length(trees), function(i) {
... ...
@@ -31,9 +35,22 @@
31 35
 ##' 	dates <- estimate.dates(tree, 1:10, mu=1, nsteps=1)
32 36
 ##' 	tree$edge.length <- dates[tree$edge[, 2]] - dates[tree$edge[, 1]]
33 37
 ##' 	fortify(tree) %>% mutate(tree=factor(i, levels=as.character(1:10)))
34
-##' }) 
38
+##' })
39
+##' 
40
+##' # Plot multiple trees with aligned tips from muliple time points
35 41
 ##' ggdensitree(time.trees, aes(colour=tree), tip.order=paste0("t", 1:10)) + geom_tiplab(colour='black')
36
-ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mds',
42
+##' 
43
+##' 
44
+##' # Read example data
45
+##' trees <- read.tree(system.file("ggtree", "inst/examples/ggdensitree_example.tree"))
46
+##' 
47
+##' # Compute OTU
48
+##' grp <- list(A = c("a.t1", "a.t2", "a.t3", "a.t4"), B = c("b.t1", "b.t2", "b.t3", "b.t4"), C = c("c.t1", "c.t2", "c.t3", "c.t4"))
49
+##' trees <- lapply(trees, groupOTU, grp)
50
+##' 
51
+##' # Plot multiple trees colored by OTU
52
+##' ggdensitree(trees, aes(colour=group), alpha=1/6) + scale_colour_manual(values=c("black", "red", "green", "blue"))
53
+ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mds_dist',
37 54
 						align.tips=TRUE, jitter=0, ...) {
38 55
 	## factorize to simplify code
39 56
 	trees <- lapply(data, as.phylo)
... ...
@@ -42,7 +59,7 @@ ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='md
42 59
 	
43 60
 	## determine tip order
44 61
 	if (length(tip.order) == 1) {
45
-		if (tip.order == 'mds') {
62
+		if (grepl('mds', tip.order)) {
46 63
 			first.label <- trees.f[[1]] %>%
47 64
 				dplyr::filter(.data$isTip) %>%
48 65
 				dplyr::pull(.data$label)
... ...
@@ -96,7 +113,7 @@ ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='md
96 113
 
97 114
 ## wrapper for cohpenetic to ensure that branch lengths exist
98 115
 cophenetic.phylo.check.length <- function(tree) {
99
-	if (is.null(tree$edge.length))
116
+	if (method != 'mds_dist' || is.null(tree$edge.length))
100 117
 		tree$edge.length <- rep(1, nrow(tree$edge))
101 118
 	
102 119
 	stats::cophenetic(tree)
Browse code

Changes to ggdensitree removed branch.length default dangle -> align.tips added branch length to example added new example with heterochronous tips

brj1 authored on 11/09/2019 18:14:26
Showing 1 changed files
... ...
@@ -4,9 +4,8 @@
4 4
 ##' @param data a list of phylo objects or any object with an as.phylo and fortify method
5 5
 ##' @param mapping aesthetic mapping
6 6
 ##' @param layout one of 'slanted', 'rectangluar', 'fan', 'circular' or 'radial' (default: 'slanted')
7
-##' @param branch.length variable to be used to scale branch length. Setting to 'branch.length' will use the branch lengths of the tree objects. Default is 'none' to discard branch length and only plot cladogram (more reasonable for densitree).
8 7
 ##' @param tip.order the order of the tips by a character vector of taxa names; or an integer, N, to order the tips by the order of the tips in the Nth tree; or 'mds' to order the tips based on MDS of the distance between the tips (default: 'mds')
9
-##' @param dangle TRUE to align trees by their tips and FALSE to align treesby their root (default: TRUE)
8
+##' @param align.tips TRUE to align trees by their tips and FALSE to align trees by their root (default: TRUE)
10 9
 ##' @param jitter deviation to jitter tips
11 10
 ##' @param ... additional parameters passed to fortify, ggtree and geom_tree
12 11
 ##' @return tree layer
... ...
@@ -17,78 +16,88 @@
17 16
 ##' @examples
18 17
 ##' require(ape)
19 18
 ##' require(dplyr)
20
-##' library(ape)
21 19
 ##' 
22
-##' trees <- list(read.tree(text="((a,b),c);"), read.tree(text="((a,c),b);"));
20
+##' trees <- list(read.tree(text="((a:1,b:1):1.5,c:2.5);"), read.tree(text="((a:1,c:1):1,b:2);"));
23 21
 ##' ggdensitree(trees) + geom_tiplab()
24 22
 ##' 
25 23
 ##' trees.fort <- list(trees[[1]] %>% fortify %>% mutate(tree="a"), trees[[2]] %>% fortify %>% mutate(tree="b"));
26 24
 ##' ggdensitree(trees.fort, aes(colour=tree)) + geom_tiplab(colour='black')
27
-ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", branch.length = "none",
28
-                        tip.order='mds', dangle=TRUE, jitter=0, ...) {
29
-    ## factorize to simplify code
30
-    trees <- lapply(data, as.phylo)
31
-    trees.f <- lapply(data, fortify, layout=layout, branch.length = branch.length, ...)
32
-    n.tips <- sum(trees.f[[1]]$isTip)
33
-
34
-    ## determine tip order
35
-    if (length(tip.order) == 1) {
36
-        if (tip.order == 'mds') {
37
-            first.label <- trees.f[[1]] %>%
38
-                dplyr::filter(.data$isTip) %>%
39
-                dplyr::pull(.data$label)
40
-            
41
-            tip.order <- lapply(trees, function(x) {
42
-                match(x$tip.label, first.label)
43
-            })
44
-            
45
-            tip.2.tip <- lapply(trees, cophenetic.phylo.check.length)
46
-            tip.2.tip <- lapply(1:length(trees), function(i) {
47
-                tip.2.tip[[i]][tip.order[[i]], tip.order[[i]]]
48
-            })
49
-            
50
-            all.tab <- do.call(rbind, tip.2.tip)
51
-            rownames(all.tab) <- NULL
52
-            
53
-            distances <- stats::dist(t(all.tab))
54
-            
55
-            res <- stats::cmdscale(distances, k=1)
25
+##' 
26
+##' set.seed(1)
27
+##' trees <- rmtree(5, 10)
28
+##' time.trees <- lapply(1:length(trees), function(i) {
29
+##'  	tree <- trees[[i]]
30
+##'  	tree$tip.label <- paste0("t", 1:10)
31
+##' 	dates <- estimate.dates(tree, 1:10, mu=1, nsteps=1)
32
+##' 	tree$edge.length <- dates[tree$edge[, 2]] - dates[tree$edge[, 1]]
33
+##' 	fortify(tree) %>% mutate(tree=factor(i, levels=as.character(1:10)))
34
+##' }) 
35
+##' ggdensitree(time.trees, aes(colour=tree), tip.order=paste0("t", 1:10)) + geom_tiplab(colour='black')
36
+ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mds',
37
+						align.tips=TRUE, jitter=0, ...) {
38
+	## factorize to simplify code
39
+	trees <- lapply(data, as.phylo)
40
+	trees.f <- lapply(data, fortify, layout=layout, ...)
41
+	n.tips <- sum(trees.f[[1]]$isTip)
42
+	
43
+	## determine tip order
44
+	if (length(tip.order) == 1) {
45
+		if (tip.order == 'mds') {
46
+			first.label <- trees.f[[1]] %>%
47
+				dplyr::filter(.data$isTip) %>%
48
+				dplyr::pull(.data$label)
49
+			
50
+			tip.order <- lapply(trees, function(x) {
51
+				match(x$tip.label, first.label)
52
+			})
53
+			
54
+			tip.2.tip <- lapply(trees, cophenetic.phylo.check.length)
55
+			tip.2.tip <- lapply(1:length(trees), function(i) {
56
+				tip.2.tip[[i]][tip.order[[i]], tip.order[[i]]]
57
+			})
58
+			
59
+			all.tab <- do.call(rbind, tip.2.tip)
60
+			rownames(all.tab) <- NULL
56 61
 			
57
-            tip.order <- first.label[order(res[,1])]
58
-        } else if (as.numeric(tip.order) && tip.order <= length(trees)) {
59
-            labels <- trees.f[[tip.order]] %>%
60
-                dplyr::filter(.data$isTip) %>%
61
-                dplyr::pull(.data$label)
62
-            
63
-            tip.order <- labels[as.integer(trees.f[[tip.order]]$y)]
64
-        }
65
-    }
62
+			distances <- stats::dist(t(all.tab))
63
+			
64
+			res <- stats::cmdscale(distances, k=1)
65
+			
66
+			tip.order <- first.label[order(res[,1])]
67
+		} else if (as.numeric(tip.order) && tip.order <= length(trees)) {
68
+			labels <- trees.f[[tip.order]] %>%
69
+				dplyr::filter(.data$isTip) %>%
70
+				dplyr::pull(.data$label)
71
+			
72
+			tip.order <- labels[as.integer(trees.f[[tip.order]]$y)]
73
+		}
74
+	}
66 75
 	
67
-    ## reorder tips (and shift x id dangling)
68
-    max.x <- vapply(trees.f, function(x) max(x$x, na.rm = TRUE), numeric(1))
69
-    farthest <- max(max.x)
70
-    trees.f <- lapply(1:length(trees), function(i) {
71
-        trees.f[[i]]$y <- getYcoord(trees[[i]], tip.order = tip.order)
72
-        if (dangle) {
73
-            trees.f[[i]]$x <- trees.f[[i]]$x + (farthest - max.x[i])
74
-        }
75
-        if (i > 1 && jitter > 0) {
76
-            trees.f[[i]]$y[1:n.tips] %<>% add(stats::rnorm(n.tips, mean=0, sd=jitter))
77
-        }
78
-        trees.f[[i]]
79
-    })
80
-    
81
-    ## plot all trees together
82
-    p <- ggtree(tr=trees.f[[1]], mapping=mapping, layout=layout, ...)
83
-    for (x in trees.f[-1])
84
-        p <- p + geom_tree(mapping=mapping, data=x, layout=layout, ...)
85
-    p
76
+	## reorder tips (and shift x id align tips)
77
+	max.x <- vapply(trees.f, function(x) max(x$x, na.rm = TRUE), numeric(1))
78
+	farthest <- max(max.x)
79
+	trees.f <- lapply(1:length(trees), function(i) {
80
+		trees.f[[i]]$y <- getYcoord(trees[[i]], tip.order = tip.order)
81
+		if (align.tips) {
82
+			trees.f[[i]]$x <- trees.f[[i]]$x + (farthest - max.x[i])
83
+		}
84
+		if (i > 1 && jitter > 0) {
85
+			trees.f[[i]]$y[1:n.tips] %<>% add(stats::rnorm(n.tips, mean=0, sd=jitter))
86
+		}
87
+		trees.f[[i]]
88
+	})
89
+	
90
+	## plot all trees together
91
+	p <- ggtree(tr=trees.f[[1]], mapping=mapping, layout=layout, ...)
92
+	for (x in trees.f[-1])
93
+		p <- p + geom_tree(mapping=mapping, data=x, layout=layout, ...)
94
+	p
86 95
 }
87 96
 
88 97
 ## wrapper for cohpenetic to ensure that branch lengths exist
89 98
 cophenetic.phylo.check.length <- function(tree) {
90
-    if (is.null(tree$edge.length))
91
-        tree$edge.length <- rep(1, nrow(tree$edge))
92
-    
93
-    stats::cophenetic(tree)
94
-}
99
+	if (is.null(tree$edge.length))
100
+		tree$edge.length <- rep(1, nrow(tree$edge))
101
+	
102
+	stats::cophenetic(tree)
103
+}
95 104
\ No newline at end of file
Browse code

ggdensitree

Guangchuang Yu authored on 11/09/2019 01:39:19
Showing 1 changed files
... ...
@@ -4,6 +4,7 @@
4 4
 ##' @param data a list of phylo objects or any object with an as.phylo and fortify method
5 5
 ##' @param mapping aesthetic mapping
6 6
 ##' @param layout one of 'slanted', 'rectangluar', 'fan', 'circular' or 'radial' (default: 'slanted')
7
+##' @param branch.length variable to be used to scale branch length. Setting to 'branch.length' will use the branch lengths of the tree objects. Default is 'none' to discard branch length and only plot cladogram (more reasonable for densitree).
7 8
 ##' @param tip.order the order of the tips by a character vector of taxa names; or an integer, N, to order the tips by the order of the tips in the Nth tree; or 'mds' to order the tips based on MDS of the distance between the tips (default: 'mds')
8 9
 ##' @param dangle TRUE to align trees by their tips and FALSE to align treesby their root (default: TRUE)
9 10
 ##' @param jitter deviation to jitter tips
... ...
@@ -17,106 +18,77 @@
17 18
 ##' require(ape)
18 19
 ##' require(dplyr)
19 20
 ##' library(ape)
20
-##' library(tidyverse)
21 21
 ##' 
22 22
 ##' trees <- list(read.tree(text="((a,b),c);"), read.tree(text="((a,c),b);"));
23 23
 ##' ggdensitree(trees) + geom_tiplab()
24 24
 ##' 
25 25
 ##' trees.fort <- list(trees[[1]] %>% fortify %>% mutate(tree="a"), trees[[2]] %>% fortify %>% mutate(tree="b"));
26 26
 ##' ggdensitree(trees.fort, aes(colour=tree)) + geom_tiplab(colour='black')
27
-ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mds', dangle=TRUE, jitter=0, ...) {
28
-	# factorize to simplify code
29
-	trees <- lapply(data, as.phylo)
30
-	trees.f <- lapply(data, fortify, layout=layout, ...)
31
-	n.tips <- sum(trees.f[[1]]$isTip)
32
-	
33
-	# determine tip order
34
-	if (length(tip.order) == 1) {
35
-		if (tip.order == 'mds') {
36
-			first.label <- subset(trees.f[[1]], isTip)$label
37
-			
38
-			tip.order <- lapply(trees, . %$% tip.label %>% match(first.label))
39
-			
40
-			tip.2.tip <- lapply(trees, cophenetic.phylo.check.length)
41
-			tip.2.tip <- lapply(1:length(trees), function(i) tip.2.tip[[i]][tip.order[[i]], tip.order[[i]]])
42
-			
43
-			all.tab <- do.call(rbind, tip.2.tip)
44
-			rownames(all.tab) <- NULL
45
-			
46
-			distances <- dist(t(all.tab))
47
-			
48
-			res <- cmdscale(distances, k=1)
49
-			
50
-			tip.order <- first.label[order(res[,1])]
51
-		} else if (as.numeric(tip.order) && tip.order <= length(trees)) {
52
-			labels <- subset(trees.f[[tip.order]], isTip)$label
27
+ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", branch.length = "none",
28
+                        tip.order='mds', dangle=TRUE, jitter=0, ...) {
29
+    ## factorize to simplify code
30
+    trees <- lapply(data, as.phylo)
31
+    trees.f <- lapply(data, fortify, layout=layout, branch.length = branch.length, ...)
32
+    n.tips <- sum(trees.f[[1]]$isTip)
33
+
34
+    ## determine tip order
35
+    if (length(tip.order) == 1) {
36
+        if (tip.order == 'mds') {
37
+            first.label <- trees.f[[1]] %>%
38
+                dplyr::filter(.data$isTip) %>%
39
+                dplyr::pull(.data$label)
40
+            
41
+            tip.order <- lapply(trees, function(x) {
42
+                match(x$tip.label, first.label)
43
+            })
44
+            
45
+            tip.2.tip <- lapply(trees, cophenetic.phylo.check.length)
46
+            tip.2.tip <- lapply(1:length(trees), function(i) {
47
+                tip.2.tip[[i]][tip.order[[i]], tip.order[[i]]]
48
+            })
49
+            
50
+            all.tab <- do.call(rbind, tip.2.tip)
51
+            rownames(all.tab) <- NULL
52
+            
53
+            distances <- stats::dist(t(all.tab))
54
+            
55
+            res <- stats::cmdscale(distances, k=1)
53 56
 			
54
-			tip.order <- labels[as.integer(trees.f[[tip.order]]$y)]
55
-		}
56
-	}
57
+            tip.order <- first.label[order(res[,1])]
58
+        } else if (as.numeric(tip.order) && tip.order <= length(trees)) {
59
+            labels <- trees.f[[tip.order]] %>%
60
+                dplyr::filter(.data$isTip) %>%
61
+                dplyr::pull(.data$label)
62
+            
63
+            tip.order <- labels[as.integer(trees.f[[tip.order]]$y)]
64
+        }
65
+    }
57 66
 	
58
-	# reorder tips (and shift x id dangling)
67
+    ## reorder tips (and shift x id dangling)
68
+    max.x <- vapply(trees.f, function(x) max(x$x, na.rm = TRUE), numeric(1))
69
+    farthest <- max(max.x)
59 70
     trees.f <- lapply(1:length(trees), function(i) {
60
-    	trees.f[[i]]$y <- getYcoord_order(trees[[i]], tip.order)
61
-    	if (i > 1) {
62
-    		trees.f[[i]]$y[1:n.tips] %<>% add(rnorm(n.tips, mean=0, sd=jitter))
63
-    		if (dangle)
64
-   	    		trees.f[[i]]$x <- trees.f[[1]]$x[1] - trees.f[[i]]$x[match(trees.f[[1]]$label, trees.f[[i]]$label)][1] + trees.f[[i]]$x
65
-    	}
66
-    	trees.f[[i]]
71
+        trees.f[[i]]$y <- getYcoord(trees[[i]], tip.order = tip.order)
72
+        if (dangle) {
73
+            trees.f[[i]]$x <- trees.f[[i]]$x + (farthest - max.x[i])
74
+        }
75
+        if (i > 1 && jitter > 0) {
76
+            trees.f[[i]]$y[1:n.tips] %<>% add(stats::rnorm(n.tips, mean=0, sd=jitter))
77
+        }
78
+        trees.f[[i]]
67 79
     })
68
-	
69
-    # plot all trees together
70
-	p <- ggtree(tr=trees.f[[1]], mapping=mapping, layout=layout, ...)
71
-	for (x in trees.f[-1])
72
-		p <- p + geom_tree(mapping=mapping, data=x, layout=layout, ...)
73
-	p
80
+    
81
+    ## plot all trees together
82
+    p <- ggtree(tr=trees.f[[1]], mapping=mapping, layout=layout, ...)
83
+    for (x in trees.f[-1])
84
+        p <- p + geom_tree(mapping=mapping, data=x, layout=layout, ...)
85
+    p
74 86
 }
75 87
 
76 88
 ## wrapper for cohpenetic to ensure that branch lengths exist
77 89
 cophenetic.phylo.check.length <- function(tree) {
78
-	if (is.null(tree$edge.length))
79
-		tree$edge.length <- rep(1, nrow(tree$edge))
80
-	
81
-	cophenetic(tree)
82
-}
83
-
84
-## this is an adaptation of old code in ggtree
85
-## 
86
-##' @importFrom magrittr %>%
87
-##' @importFrom magrittr equals
88
-getYcoord_order <- function(tr, tip.order) {
89
-    Ntip <- length(tr[["tip.label"]])
90
-    N <- getNodeNum(tr)
91
-
92
-    edge <- tr[["edge"]]
93
-    parent <- edge[,1]
94
-    child <- edge[,2]
95
-
96
-    cl <- split(child, parent)
97
-    child_list <- list()
98
-    child_list[as.numeric(names(cl))] <- cl
99
-
100
-    y <- numeric(N)
101
-    y[1:Ntip] <- match(tr$tip.label, tip.order)
102
-    y[-(1:Ntip)] <- NA
103
-
104
-    pvec <- integer(max(tr$edge))
105
-    pvec[child] = parent
106
-
107
-    currentNode <- 1:Ntip
108
-    while(anyNA(y)) {
109
-        pNode <- unique(pvec[currentNode])
110
-
111
-        idx <- sapply(pNode, function(i) all(child_list[[i]] %in% currentNode))
112
-        newNode <- pNode[idx]
113
-
114
-        y[newNode] <- sapply(newNode, function(i) {
115
-            mean(y[child_list[[i]]], na.rm=TRUE)
116
-        })
117
-
118
-        currentNode <- c(currentNode[!currentNode %in% unlist(child_list[newNode])], newNode)
119
-    }
120
-
121
-    return(y)
90
+    if (is.null(tree$edge.length))
91
+        tree$edge.length <- rep(1, nrow(tree$edge))
92
+    
93
+    stats::cophenetic(tree)
122 94
 }
Browse code

Added ggdensitree method ggdensitree can plot lists of phylogenetic trees (or list of treedata) such that - tips are aligned in the y axis and - tips can optionally (actually default) be aligned in the x axis - colouring of edges can be match to an aesthetic/scale Node and tip labelling can only be done on the first tree in the list

brj1 authored on 10/09/2019 22:31:48
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,122 @@
1
+##' drawing phylogenetic trees from list of phylo objects
2
+##'
3
+##' @title ggdensitree
4
+##' @param data a list of phylo objects or any object with an as.phylo and fortify method
5
+##' @param mapping aesthetic mapping
6
+##' @param layout one of 'slanted', 'rectangluar', 'fan', 'circular' or 'radial' (default: 'slanted')
7
+##' @param tip.order the order of the tips by a character vector of taxa names; or an integer, N, to order the tips by the order of the tips in the Nth tree; or 'mds' to order the tips based on MDS of the distance between the tips (default: 'mds')
8
+##' @param dangle TRUE to align trees by their tips and FALSE to align treesby their root (default: TRUE)
9
+##' @param jitter deviation to jitter tips
10
+##' @param ... additional parameters passed to fortify, ggtree and geom_tree
11
+##' @return tree layer
12
+##' @importFrom magrittr %<>%
13
+##' @importFrom magrittr add
14
+##' @export
15
+##' @author Yu Guangchuang, Bradley R. Jones
16
+##' @examples
17
+##' require(ape)
18
+##' require(dplyr)
19
+##' library(ape)
20
+##' library(tidyverse)
21
+##' 
22
+##' trees <- list(read.tree(text="((a,b),c);"), read.tree(text="((a,c),b);"));
23
+##' ggdensitree(trees) + geom_tiplab()
24
+##' 
25
+##' trees.fort <- list(trees[[1]] %>% fortify %>% mutate(tree="a"), trees[[2]] %>% fortify %>% mutate(tree="b"));
26
+##' ggdensitree(trees.fort, aes(colour=tree)) + geom_tiplab(colour='black')
27
+ggdensitree <- function(data=NULL, mapping=NULL, layout="slanted", tip.order='mds', dangle=TRUE, jitter=0, ...) {
28
+	# factorize to simplify code
29
+	trees <- lapply(data, as.phylo)
30
+	trees.f <- lapply(data, fortify, layout=layout, ...)
31
+	n.tips <- sum(trees.f[[1]]$isTip)
32
+	
33
+	# determine tip order
34
+	if (length(tip.order) == 1) {
35
+		if (tip.order == 'mds') {
36
+			first.label <- subset(trees.f[[1]], isTip)$label
37
+			
38
+			tip.order <- lapply(trees, . %$% tip.label %>% match(first.label))
39
+			
40
+			tip.2.tip <- lapply(trees, cophenetic.phylo.check.length)
41
+			tip.2.tip <- lapply(1:length(trees), function(i) tip.2.tip[[i]][tip.order[[i]], tip.order[[i]]])
42
+			
43
+			all.tab <- do.call(rbind, tip.2.tip)
44
+			rownames(all.tab) <- NULL
45
+			
46
+			distances <- dist(t(all.tab))
47
+			
48
+			res <- cmdscale(distances, k=1)
49
+			
50
+			tip.order <- first.label[order(res[,1])]
51
+		} else if (as.numeric(tip.order) && tip.order <= length(trees)) {
52
+			labels <- subset(trees.f[[tip.order]], isTip)$label
53
+			
54
+			tip.order <- labels[as.integer(trees.f[[tip.order]]$y)]
55
+		}
56
+	}
57
+	
58
+	# reorder tips (and shift x id dangling)
59
+    trees.f <- lapply(1:length(trees), function(i) {
60
+    	trees.f[[i]]$y <- getYcoord_order(trees[[i]], tip.order)
61
+    	if (i > 1) {
62
+    		trees.f[[i]]$y[1:n.tips] %<>% add(rnorm(n.tips, mean=0, sd=jitter))
63
+    		if (dangle)
64
+   	    		trees.f[[i]]$x <- trees.f[[1]]$x[1] - trees.f[[i]]$x[match(trees.f[[1]]$label, trees.f[[i]]$label)][1] + trees.f[[i]]$x
65
+    	}
66
+    	trees.f[[i]]
67
+    })
68
+	
69
+    # plot all trees together
70
+	p <- ggtree(tr=trees.f[[1]], mapping=mapping, layout=layout, ...)
71
+	for (x in trees.f[-1])
72
+		p <- p + geom_tree(mapping=mapping, data=x, layout=layout, ...)
73
+	p
74
+}
75
+
76
+## wrapper for cohpenetic to ensure that branch lengths exist
77
+cophenetic.phylo.check.length <- function(tree) {
78
+	if (is.null(tree$edge.length))
79
+		tree$edge.length <- rep(1, nrow(tree$edge))
80
+	
81
+	cophenetic(tree)
82
+}
83
+
84
+## this is an adaptation of old code in ggtree
85
+## 
86
+##' @importFrom magrittr %>%
87
+##' @importFrom magrittr equals
88
+getYcoord_order <- function(tr, tip.order) {
89
+    Ntip <- length(tr[["tip.label"]])
90
+    N <- getNodeNum(tr)
91
+
92
+    edge <- tr[["edge"]]
93
+    parent <- edge[,1]
94
+    child <- edge[,2]
95
+
96
+    cl <- split(child, parent)
97
+    child_list <- list()
98
+    child_list[as.numeric(names(cl))] <- cl
99
+
100
+    y <- numeric(N)
101
+    y[1:Ntip] <- match(tr$tip.label, tip.order)
102
+    y[-(1:Ntip)] <- NA
103
+
104
+    pvec <- integer(max(tr$edge))
105
+    pvec[child] = parent
106
+
107
+    currentNode <- 1:Ntip
108
+    while(anyNA(y)) {
109
+        pNode <- unique(pvec[currentNode])
110
+
111
+        idx <- sapply(pNode, function(i) all(child_list[[i]] %in% currentNode))
112
+        newNode <- pNode[idx]
113
+
114
+        y[newNode] <- sapply(newNode, function(i) {
115
+            mean(y[child_list[[i]]], na.rm=TRUE)
116
+        })
117
+
118
+        currentNode <- c(currentNode[!currentNode %in% unlist(child_list[newNode])], newNode)
119
+    }
120
+
121
+    return(y)
122
+}