forked from microsud/microbiomeutilities
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplot_taxa_composition.R
More file actions
190 lines (183 loc) · 8.17 KB
/
Copy pathplot_taxa_composition.R
File metadata and controls
190 lines (183 loc) · 8.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#' @title Taxonomic Composition Plot
#' @description Plot taxon abundance for samples. It is a legacy function from \code{\link{microbiome}}.
#' @param x \code{\link{phyloseq-class}} object
#' @param taxonomic.level Merge the OTUs (for phyloseq object) into a higher taxonomic level. This has to be one from colnames(tax_table(x)).
#' @param sample.sort Order samples. Various criteria are available:
#' \itemize{
#' \item NULL or 'none': No sorting
#' \item A single character string: indicate the metadata field to be used for ordering
#' \item A character vector: sample IDs indicating the sample ordering.
#' \item 'neatmap' Order samples based on the neatmap approach. See \code{\link{neatsort}}. By default, 'NMDS' method with 'bray' distance is used. For other options, arrange the samples manually with the function.
#' }
#' @param otu.sort Order taxa. Same options as for the sample.sort argument but instead of metadata, taxonomic table is used. Also possible to sort by 'abundance'.
#' @param x.label Specify how to label the x axis. This should be one of the variables in sample_variables(x).
#' @param plot.type Plot type: 'barplot' or 'lineplot'.
#' @param verbose verbose.
#' @param transform Data transform to be used in plotting (but not in sample/taxon ordering). The options are 'Z-OTU', 'Z-Sample', 'log10' and 'compositional'. See the \code{\link{transform}} function.
#' @param mar Figure margins.
#' @param average_by Variable to group.
#' @param palette The number and palette \code{\link{RColorBrewer}} has to be specified e.g brewer.pal(12, "Paired").
#' @param ... Arguments to be passed (for \code{\link{neatsort}} function)
#' @return A \code{\link{ggplot}} plot object.
#' @export
#' @examples \dontrun{
#' # Example data
#' library(microbiome)
#' library(microbiomeutilities)
#' data("biogeogut")
#' pseq <- biogeogut
#' plot_taxa_composition(pseq, taxonomic.level = "Phylum")
#' }
#' @keywords utilities
plot_taxa_composition <- function (x, sample.sort = NULL,
taxonomic.level = "Phylum",
transform = "compositional",
otu.sort = NULL,
palette = brewer.pal(12, "Paired"),
x.label = "sample",
plot.type = "barplot", average_by = NULL,
verbose = FALSE,
mar = c(5, 12, 1,1), ...)
{
Sample <- Abundance <- Taxon <- horiz <- value <- scales <- ID <- meta <- OTU <- taxic <- otu.df <- taxmat <- new.tax <- NULL
if (!is.null(x@phy_tree)) {
x@phy_tree = NULL
}
taxic <- x@tax_table
taxic <- as.data.frame.matrix(taxic)
otu.df <- abundances(x)
otu.df <- as.data.frame.matrix(otu.df)
taxic$OTU <- row.names(otu.df)
taxmat <- as.matrix(taxic)
new.tax <- tax_table(taxmat)
tax_table(x) <- new.tax
xorig <- x
# Merge the taxa at a higher taxonomic level
if (!taxonomic.level == "OTU") {
if (verbose) {
message("Aggregating the taxa.")
}
x <- aggregate_taxa(x, taxonomic.level)
}
if (verbose) {
message("Check data transforms.")
}
if (is.null(transform)) {
x <- x
} else if (transform == "Z-OTU") {
x <- microbiome::transform(x, "Z", "OTU")
} else if (transform == "Z-Sample") {
x <- microbiome::transform(x, "Z", "Sample")
} else if (transform == "compositional") {
x <- microbiome::transform(x, "compositional")
} else {
x <- microbiome::transform(x, transform)
}
abu <- abundances(x)
group <- NULL
if (!is.null(average_by)) {
dff <- as.data.frame(t(abu))
dff$group <- sample_data(x)[[average_by]]
if (is.numeric(dff$group)) {
dff$group <- factor(dff$group, levels = sort(unique(dff$group)))
}
dff <- dff %>% filter(!is.na(group))
dff$group <- droplevels(dff$group)
av <- aggregate(. ~ group, data = dff, mean)
rownames(av) <- as.character(av$group)
av$group <- NULL
abu <- t(av)
}
if (is.null(sample.sort) || sample.sort == "none" || !is.null(average_by)) {
sample.sort <- colnames(abu)
}
else if (length(sample.sort) == 1 && sample.sort %in% names(sample_data(x)) &&
is.null(average_by)) {
sample.sort <- rownames(sample_data(x))[order(sample_data(x)[[sample.sort]])]
}
else if (all(sample.sort %in% sample_names(x)) & is.null(average_by)) {
sample.sort <- sample.sort
}
else if (length(sample.sort) == 1 && sample.sort == "neatmap") {
sample.sort <- neatsort(x, method = "NMDS", distance = "bray",
target = "sites", first = NULL)
}
else if (!sample.sort %in% names(sample_data(x))) {
warning(paste("The sample.sort argument", sample.sort,
"is not included in sample_data(x). \n Using original sample ordering."))
sample.sort <- sample_names(x)
}
if (is.null(otu.sort) || otu.sort == "none") {
otu.sort <- taxa(x)
}
else if (length(otu.sort) == 1 && otu.sort == "abundance") {
otu.sort <- rev(names(sort(rowSums(abu))))
}
else if (length(otu.sort) == 1 && otu.sort %in% names(tax_table(x))) {
otu.sort <- rownames(sample_data(x))[order(tax_table(x)[[otu.sort]])]
}
else if (all(otu.sort %in% taxa(x))) {
otu.sort <- otu.sort
}
else if (length(otu.sort) == 1 && otu.sort == "neatmap") {
otu.sort <- neatsort(x, method = "NMDS", distance = "bray",
target = "species", first = NULL)
}
if (verbose) {
message("Prepare data.frame.")
}
dfm <- psmelt(otu_table(abu, taxa_are_rows = TRUE))
names(dfm) <- c("OTU", "Sample", "Abundance")
dfm$Sample <- factor(dfm$Sample, levels = sample.sort)
dfm$OTU <- factor(dfm$OTU, levels = otu.sort)
colourCount = length(unique(dfm$OTU)) #define number of variable colors based on number of Family (change the level accordingly to phylum/class/order)
getPalette = colorRampPalette(palette)
if (x.label %in% colnames(sample_data(x)) & is.null(average_by)) {
meta <- sample_data(x)
dfm$xlabel <- as.vector(unlist(meta[as.character(dfm$Sample),
x.label]))
if (is.factor(meta[, x.label])) {
lev <- levels(meta[, x.label])
}
else {
lev <- unique(as.character(unname(unlist(meta[,
x.label]))))
}
dfm$xlabel <- factor(dfm$xlabel, levels = lev)
}
else {
dfm$xlabel <- dfm$Sample
}
if (verbose) {
message("Construct the plots")
}
if (plot.type == "barplot") {
dfm <- dfm %>% arrange(OTU)
p <- ggplot(dfm, aes(x = Sample, y = Abundance, fill = OTU))
p <- p + geom_bar(position = "stack", stat = "identity")
p <- p + scale_x_discrete(labels = dfm$xlabel, breaks = dfm$Sample)
p <- p + ylab("Abundance") + scale_fill_manual(taxonomic.level, values = getPalette(colourCount))
p <- p + theme(axis.text.x = element_text(angle = 90,
vjust = 0.5, hjust = 0))
p <- p + guides(fill = guide_legend(reverse = FALSE))
}
else if (plot.type == "lineplot") {
dfm <- dfm %>% arrange(OTU)
p <- ggplot(dfm, aes(x = Sample, y = Abundance, color = OTU,
group = OTU))
p <- p + geom_point()
p <- p + geom_line() + scale_color_brewer(guide = guide_legend(title = taxonomic.level))
p <- p + scale_x_discrete(labels = dfm$xlabel, breaks = dfm$Sample)
if (!is.null(transform) && transform == "compositional") {
suppressMessages(p <- p + ylab("Relative abundance (%)") + scale_color_manual(taxonomic.level, values = getPalette(colourCount)))
}
else {
p <- p + ylab("Abundance")
}
p <- p + theme(axis.text.x = element_text(angle = 90,
vjust = 0.5, hjust = 0))
suppressMessages(p <- p + guides(fill = guide_legend(reverse = FALSE)) +
scale_color_manual(taxonomic.level, values = getPalette(colourCount)))
}
p + theme_bw() + theme(axis.text.x = element_text(face ="italic", angle = 90))
}