|
| 1 | +#' @title A paired-boxplot for user specified list of taxa |
| 2 | +#' @description User specified taxa are plotted. |
| 3 | +#' @details Useful for instances where user is interested only in some taxa and thier change after |
| 4 | +#' an intervention. This can also be used at higher taxonomic |
| 5 | +#' levels, output from phyloseq::tax_glom or microbiome::aggregate_taxa. |
| 6 | +#' |
| 7 | +#' @param x \code{\link{phyloseq-class}} object. |
| 8 | +#' @param select.taxa a character list of taxa to be plotted. eg. select.taxa <- c("OTU-370251", "OTU-311173", "OTU-341024"). |
| 9 | +#' @param group Grouping variable to compare. x axis, eg. before-after, t1-t2. |
| 10 | +#' @param group.colors Colors for plotting groups. |
| 11 | +#' @param dot.opacity For ggplot alpha to determine opacity for points. |
| 12 | +#' @param dot.size For ggplot point size. |
| 13 | +#' @param jitter.width Value to avoid over plotting by moving points. |
| 14 | +#' @param add.box Logical. If boxplot to the added. Default=TRUE |
| 15 | +#' @param box.opacity For ggplot alpha to determine opacity for box. |
| 16 | +#' @param add.violin Logical. If half violin to the added. Default=TRUE |
| 17 | +#' @param violin.opacity If add.violin=TRUE, opacity for violin. |
| 18 | +#' @param group.order Default is NULL. a list specifying order of x-axis. |
| 19 | +#' @param ncol If 2 or more taxa to plot, specify number of columns. |
| 20 | +#' @param nrow If 2 or more taxa to plot, specify number of rows. |
| 21 | +#' @param line Variable to use for lines. E.g. "subject" before-after |
| 22 | +#' @param line.down Line Color for change when negative. Decreased abundance. |
| 23 | +#' @param line.stable Line Color for no change. |
| 24 | +#' @param line.up Line Color for change when positive. Increased abundance. |
| 25 | +#' @param line.na.value "grey50" for no/missing observations. |
| 26 | +#' @param line.guide "none" to plot guide for line. |
| 27 | +#' @param line.opacity Line opacity. |
| 28 | +#' @param line.size Size of line to plot. |
| 29 | +#' |
| 30 | +#' @return \code{\link{ggplot}} object. This can be further modified using ggpubr. |
| 31 | +#' @importFrom tidyr pivot_longer |
| 32 | +#' @export |
| 33 | +#' @examples |
| 34 | +#' \dontrun{ |
| 35 | +#' library(microbiome) |
| 36 | +#' library(microbiomeutilities) |
| 37 | +#' library(gghalves) |
| 38 | +#' library(tidyr) |
| 39 | +#' data(peerj32) # Source: https://peerj.com/articles/32/ |
| 40 | +#' pseq <- peerj32$phyloseq # Ren |
| 41 | +#' pseq.rel <- microbiome::transform(pseq, "compositional") |
| 42 | +#' select.taxa <- c("Akkermansia", "Dialister") |
| 43 | +#' group.colors <- c("brown3", "steelblue", "grey70") |
| 44 | +#' p <- plot_paired_abundances(pseq.rel, |
| 45 | +#' select.taxa = select.taxa, |
| 46 | +#' group = "time", |
| 47 | +#' group.colors = group.colors, |
| 48 | +#' dot.opacity = 0.25, |
| 49 | +#' dot.size = 2, |
| 50 | +#' group.order = NULL, |
| 51 | +#' line = "subject" |
| 52 | +#' ) |
| 53 | +#' p |
| 54 | +#' } |
| 55 | +#' @keywords visualization |
| 56 | + |
| 57 | +plot_paired_abundances <- function(x, |
| 58 | + select.taxa = NULL, |
| 59 | + group = NULL, |
| 60 | + group.colors = NULL, |
| 61 | + dot.opacity = 0.25, |
| 62 | + dot.size = 2, |
| 63 | + add.box = FALSE, |
| 64 | + box.opacity = 0.25, |
| 65 | + group.order = NULL, |
| 66 | + add.violin = TRUE, |
| 67 | + violin.opacity = 0.25, |
| 68 | + ncol = NULL, |
| 69 | + nrow = NULL, |
| 70 | + line = NULL, |
| 71 | + line.down = "#7209b7", |
| 72 | + line.stable = "#8d99ae", |
| 73 | + line.up = "#14213d", |
| 74 | + line.na.value = "grey50", |
| 75 | + line.guide = "legend", |
| 76 | + line.opacity = 0.25, |
| 77 | + line.size = 1, |
| 78 | + jitter.width = 0) { |
| 79 | + Abundance <- change <- change.order <- change.sign <- linevar <- NULL |
| 80 | + # check arguments |
| 81 | + if (is.na(line) | is.null(line)) { |
| 82 | + stop(" 'line' argument cannot be empty") |
| 83 | + } |
| 84 | + |
| 85 | + if (is.na(group) | is.null(group)) { |
| 86 | + stop(" 'group' argument cannot be empty") |
| 87 | + } |
| 88 | + #x <- pseq.rel |
| 89 | + xmeta <- meta(x) |
| 90 | + for (i in select.taxa) { |
| 91 | + df.tx <- as.data.frame(abundances(x)[i, ]) |
| 92 | + colnames(df.tx) <- i |
| 93 | + xmeta <- cbind(xmeta, df.tx) |
| 94 | + } |
| 95 | + |
| 96 | + if(length(unique(xmeta[, group])) > 2){ |
| 97 | + stop("Only two group comparison e.g. before n after") |
| 98 | + } |
| 99 | + |
| 100 | + # check if factor else convert to factor |
| 101 | + if (!is.factor(xmeta[, group])) { |
| 102 | + xmeta$group <- factor(as.character(xmeta[, group])) |
| 103 | + } |
| 104 | + |
| 105 | + # convert to wide format |
| 106 | + xmeta_lf <- xmeta %>% |
| 107 | + pivot_longer( |
| 108 | + cols = all_of(select.taxa), |
| 109 | + names_to = "taxa", |
| 110 | + values_to = "Abundance" |
| 111 | + ) |
| 112 | + |
| 113 | + xmeta_lf$linevar <- factor(xmeta_lf[[line]]) |
| 114 | + |
| 115 | + x.grp <- sym(group) |
| 116 | + |
| 117 | + df2 <- suppressWarnings(xmeta_lf %>% |
| 118 | + arrange(taxa,linevar, !!x.grp) %>% |
| 119 | + group_by(taxa,linevar) %>% |
| 120 | + summarise(change = diff(Abundance))) |
| 121 | + |
| 122 | + xmeta_lf_2 <- suppressWarnings(xmeta_lf %>% |
| 123 | + arrange(taxa,linevar, !!x.grp) %>% |
| 124 | + group_by(taxa,linevar)) |
| 125 | + |
| 126 | + xmeta_lf_2 <- xmeta_lf_2 %>% |
| 127 | + left_join(df2) |
| 128 | + |
| 129 | + #xmeta_lf$change <- df2$change[match(xmeta_lf$linevar, df2$linevar)] |
| 130 | + |
| 131 | + xmeta_lf_2$change.sign <- sign(xmeta_lf_2$change) |
| 132 | + |
| 133 | + if (!is.null(group.order)) { |
| 134 | + xmeta_lf_2[, group] <- factor(xmeta_lf_2[, group], |
| 135 | + levels = group.order |
| 136 | + ) |
| 137 | + } |
| 138 | + xmeta_lf_2 <- xmeta_lf_2 %>% |
| 139 | + mutate(change.order = ifelse(change.sign == 1, "Up", |
| 140 | + ifelse(change.sign == -1, "Down", |
| 141 | + "Stable" |
| 142 | + ) |
| 143 | + )) |
| 144 | + # start plotting |
| 145 | + p <- ggplot( |
| 146 | + data = xmeta_lf_2, |
| 147 | + aes_string( |
| 148 | + x = "group", |
| 149 | + y = "Abundance", |
| 150 | + fill = "group" |
| 151 | + ) |
| 152 | + ) + |
| 153 | + geom_point(aes_string( |
| 154 | + x = "group", |
| 155 | + fill = "group" |
| 156 | + ), |
| 157 | + position = position_jitter(width = jitter.width), |
| 158 | + size = dot.size, |
| 159 | + alpha = dot.opacity, |
| 160 | + shape = 21 |
| 161 | + ) + |
| 162 | + geom_line(aes( |
| 163 | + group = linevar, |
| 164 | + color = change.order |
| 165 | + ), |
| 166 | + size = line.size, |
| 167 | + alpha = line.opacity |
| 168 | + #lty = line.type |
| 169 | + ) |
| 170 | + |
| 171 | + p <- p + scale_fill_manual(values = group.colors) |
| 172 | + |
| 173 | + if (add.box == TRUE) { |
| 174 | + p <- p + geom_boxplot( |
| 175 | + width = 0.2, |
| 176 | + outlier.shape = NA, |
| 177 | + alpha = box.opacity |
| 178 | + ) |
| 179 | + } |
| 180 | + |
| 181 | +#geom_half_violin( |
| 182 | +# data = iris %>% filter(Species=="versicolor"), |
| 183 | +# aes(x = Species, y = Sepal.Length, fill = Species), side="r") |
| 184 | + if (add.violin == TRUE) { |
| 185 | + p <- p + geom_half_violin(data = xmeta_lf_2 %>% |
| 186 | + filter(group==unique(xmeta_lf_2$group)[1]), |
| 187 | + position = position_nudge(x = -0.15, y = 0), |
| 188 | + alpha = violin.opacity, |
| 189 | + side = "l" |
| 190 | + ) + |
| 191 | + geom_half_violin(data = xmeta_lf_2 %>% |
| 192 | + filter(group==unique(xmeta_lf_2$group)[2]), |
| 193 | + position = position_nudge(x = 0.15, y = 0), |
| 194 | + alpha = violin.opacity, |
| 195 | + side = "r" |
| 196 | + ) |
| 197 | + } |
| 198 | + |
| 199 | + if (length(select.taxa) >= 2) { |
| 200 | + p <- p + facet_wrap(~taxa, |
| 201 | + scales = "free", |
| 202 | + ncol = ncol, |
| 203 | + nrow = nrow |
| 204 | + ) |
| 205 | + } |
| 206 | + p <- p + scale_color_manual( |
| 207 | + values = c( |
| 208 | + Up = line.up, |
| 209 | + Down = line.down, |
| 210 | + Stable = line.stable |
| 211 | + ), |
| 212 | + guide = line.guide |
| 213 | + ) |
| 214 | + |
| 215 | + p <- p + theme_biome_utils() + xlab(group) |
| 216 | + |
| 217 | + return(p) |
| 218 | +} |
0 commit comments