├── .Rbuildignore ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── bias-helpers.R ├── calibrate.R ├── compositional-mean.R ├── estimate.R ├── math.R ├── mean_efficiency.R ├── metacal-package.R ├── metacal.R ├── ratios.R ├── utilities.R └── utils-pipe.R ├── README.md ├── _pkgdown.yml ├── data-raw └── brooks2015.R ├── docs ├── 404.html ├── LICENSE-text.html ├── LICENSE.html ├── articles │ ├── index.html │ ├── tutorial.html │ └── tutorial_files │ │ ├── figure-html │ │ ├── unnamed-chunk-11-1.png │ │ ├── unnamed-chunk-17-1.png │ │ ├── unnamed-chunk-20-1.png │ │ ├── unnamed-chunk-23-1.png │ │ ├── unnamed-chunk-24-1.png │ │ └── unnamed-chunk-8-1.png │ │ └── header-attrs-2.9 │ │ └── header-attrs.js ├── authors.html ├── bootstrap-toc.css ├── bootstrap-toc.js ├── docsearch.css ├── docsearch.js ├── index.html ├── link.svg ├── news │ └── index.html ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml └── reference │ ├── Rplot001.png │ ├── anorm.html │ ├── as_matrix.html │ ├── bootrep_center.html │ ├── build_matrix.html │ ├── calibrate.html │ ├── center.html │ ├── center_elts.html │ ├── close_elts.html │ ├── clr.html │ ├── compute_ratios.html │ ├── cooccurrence.html │ ├── corner.html │ ├── estimate_bias.html │ ├── gm.html │ ├── gm_abs.html │ ├── gm_mean.html │ ├── gm_range.html │ ├── gm_sd.html │ ├── import_phyloseq.html │ ├── index.html │ ├── log_center_proj.html │ ├── log_center_rss.html │ ├── logit.html │ ├── mutate_by.html │ ├── odds.html │ ├── pairwise_ratios.html │ ├── perturb.html │ ├── proj_mat.html │ └── xydist.html ├── inst └── extdata │ ├── brooks2015-actual.csv │ ├── brooks2015-observed.csv │ └── brooks2015-sample-data.csv ├── man ├── anorm.Rd ├── as_matrix.Rd ├── bootrep_center.Rd ├── build_matrix.Rd ├── calibrate.Rd ├── center.Rd ├── center_elts.Rd ├── close_elts.Rd ├── clr.Rd ├── compute_ratios.Rd ├── cooccurrence.Rd ├── corner.Rd ├── estimate_bias.Rd ├── gm.Rd ├── gm_abs.Rd ├── gm_mean.Rd ├── gm_range.Rd ├── gm_sd.Rd ├── import_phyloseq.Rd ├── log_center_proj.Rd ├── log_center_rss.Rd ├── logit.Rd ├── mean_efficiency.Rd ├── metacal-package.Rd ├── mutate_by.Rd ├── odds.Rd ├── pairwise_ratios.Rd ├── perturb.Rd ├── proj_mat.Rd └── xydist.Rd ├── tests ├── testthat.R └── testthat │ ├── test-calibrate.R │ ├── test-center.R │ ├── test-ratios.R │ └── test-utilities.R └── vignettes └── tutorial.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^metacal\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^LICENSE\.md$ 4 | ^README\.Rmd$ 5 | ^cran-comments\.md$ 6 | ^\.github$ 7 | ^data-raw$ 8 | ^docs$ 9 | ^vignettes/data$ 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | inst/doc 3 | /vignettes/data/ 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: metacal 2 | Title: Bias estimation and calibration for metagenomics experiments 3 | Version: 0.2.0.9010 4 | Authors@R: 5 | person(given = "Michael", 6 | family = "McLaren", 7 | role = c("aut", "cre"), 8 | email = "m.mclaren42@gmail.com", 9 | comment = c(ORCID = "0000-0003-1575-473X")) 10 | Description: The metacal package provides tools for bias estimation and 11 | calibration in marker-gene and metagenomics sequencing experiments, using 12 | the methods developed in https://elifesciences.org/articles/46923. 13 | URL: https://mikemc.github.io/metacal, https://github.com/mikemc/metacal 14 | BugReports: https://github.com/mikemc/metacal/issues 15 | License: MIT + file LICENSE 16 | Imports: 17 | dplyr, 18 | igraph, 19 | lifecycle, 20 | magrittr, 21 | MASS, 22 | phyloseq, 23 | purrr, 24 | rlang, 25 | tibble, 26 | tidyr, 27 | useful 28 | Suggests: 29 | testthat, 30 | roxygen2, 31 | knitr, 32 | rmarkdown, 33 | tidyverse, 34 | cowplot, 35 | ggbeeswarm, 36 | here, 37 | readr, 38 | sessioninfo 39 | Encoding: UTF-8 40 | LazyData: true 41 | Roxygen: list(markdown = TRUE) 42 | RoxygenNote: 7.1.2 43 | VignetteBuilder: knitr 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2019 2 | COPYRIGHT HOLDER: Michael R. McLaren 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2019 Michael R. McLaren 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(calibrate,matrix) 4 | S3method(calibrate,otu_table) 5 | S3method(calibrate,phyloseq) 6 | S3method(coef,mc_bias_fit) 7 | S3method(estimate_bias,matrix) 8 | S3method(estimate_bias,otu_table) 9 | S3method(estimate_bias,phyloseq) 10 | S3method(fitted,mc_bias_fit) 11 | S3method(mean_efficiency,matrix) 12 | S3method(mean_efficiency,mc_bias_fit) 13 | S3method(mean_efficiency,otu_table) 14 | S3method(mean_efficiency,phyloseq) 15 | S3method(pairwise_ratios,default) 16 | S3method(pairwise_ratios,matrix) 17 | S3method(pairwise_ratios,otu_table) 18 | S3method(pairwise_ratios,phyloseq) 19 | S3method(perturb,matrix) 20 | S3method(perturb,mc_bias_fit) 21 | S3method(perturb,otu_table) 22 | S3method(perturb,phyloseq) 23 | S3method(print,mc_bias_fit) 24 | S3method(print,mc_bias_fit_summary) 25 | S3method(residuals,mc_bias_fit) 26 | S3method(summary,mc_bias_fit) 27 | export(anorm) 28 | export(as_matrix) 29 | export(bootrep_center) 30 | export(build_matrix) 31 | export(calibrate) 32 | export(center) 33 | export(center_elts) 34 | export(close_elts) 35 | export(clr) 36 | export(compute_ratios) 37 | export(cooccurrence_components) 38 | export(cooccurrence_matrix) 39 | export(cooccurrence_network) 40 | export(corner) 41 | export(estimate_bias) 42 | export(gm) 43 | export(gm_abs) 44 | export(gm_mean) 45 | export(gm_range) 46 | export(gm_sd) 47 | export(logit) 48 | export(mean_efficiency) 49 | export(mutate_by) 50 | export(odds) 51 | export(pairwise_ratios) 52 | export(perturb) 53 | export(xydist) 54 | importClassesFrom(phyloseq,otu_table) 55 | importClassesFrom(phyloseq,phyloseq) 56 | importFrom(magrittr,"%>%") 57 | importFrom(phyloseq,"otu_table<-") 58 | importFrom(phyloseq,"sample_data<-") 59 | importFrom(phyloseq,nsamples) 60 | importFrom(phyloseq,ntaxa) 61 | importFrom(phyloseq,otu_table) 62 | importFrom(phyloseq,prune_taxa) 63 | importFrom(phyloseq,sample_data) 64 | importFrom(phyloseq,sample_names) 65 | importFrom(phyloseq,sample_sums) 66 | importFrom(phyloseq,t) 67 | importFrom(phyloseq,taxa_are_rows) 68 | importFrom(phyloseq,taxa_names) 69 | importFrom(useful,corner) 70 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # metacal (development version) 2 | 3 | * `build_matrix()` now works correctly on grouped tibbles 4 | 5 | * `pairwise_ratios()` now correctly handles phyloseq objects with just 1 sample 6 | or taxon, and is properly exported 7 | 8 | * `estimate_bias()` now allows `observed` to have extra samples and taxa not in `actual`, by automatically subsetting to those in `actual` 9 | 10 | * `calibrate()` now allows `bias` to be an 'mc_bias_fit' object 11 | 12 | * Add `mean_efficiency()` to compute mean efficiency of control or new samples 13 | 14 | * `calibrate()` now (by default) computes and adds the mean efficiency to the sample data 15 | 16 | # metacal 0.2.0 17 | 18 | ## New features 19 | 20 | ### New estimation and calibration functions 21 | 22 | `estimate_bias()` and `calibrate()` provide easy-to-use high-level interfaces to the original metacal bias-estimation and calibration method. 23 | Their use is illustrated in the new tutorial. 24 | 25 | ### New utility functions 26 | 27 | * `pairwise_ratios()` allows computing ratios between pairs of taxa and/or samples. 28 | 29 | * `perturb()` applies a compositional perturbation to all observations in an abundance matrix (or phyloseq object). 30 | 31 | ### Support for phyloseq objects 32 | 33 | The new functions `estimate_bias()`, `perturb()`, `calibrate()`, and `pairwise_ratios()` all work with objects from the [phyloseq](https://joey711.github.io/phyloseq/) package as well as plain matrices. 34 | Phyloseq is now a required dependency, though may be made optional in the future. 35 | 36 | ### New tutorial 37 | 38 | The [new tutorial](https://mikemc.github.io/metacal/articles/tutorial.html) demonstrates the new estimation and calibration functions on a new dataset from [Leopold and Busby (2020)](https://doi.org/10.1016/j.cub.2020.06.011). 39 | 40 | ## Minor fixes 41 | 42 | * Fixed failure of `coocurrence_matrix()` when names were missing (#5). 43 | 44 | # metacal 0.1.0 45 | 46 | Direct implementation of the methods described in [McLaren MR, Willis AD, Callahan BJ (2019)](https://elifesciences.org/articles/46923) and used for [the analysis of that paper](https://github.com/mikemc/mgs-bias-manuscript). 47 | -------------------------------------------------------------------------------- /R/bias-helpers.R: -------------------------------------------------------------------------------- 1 | # Functions that can help understand bias estimates 2 | 3 | # Taxon co-occurrence network ------------------------------------------------- 4 | 5 | #' Taxon co-occurrence network 6 | #' 7 | #' Functions for probing the taxon co-occurrence network, used for checking if 8 | #' the bias estimated by the `center()` function is fully-determined. 9 | #' 10 | #' The edges are weighted by the number of samples the pair of taxa co-occur in 11 | #' and so provide some information about the precision of the pairwise bias 12 | #' estimate. 13 | #' 14 | #' @param mat A compositional error matrix 15 | #' @param all Whether to include taxa that aren't in any multi-taxon samples 16 | #' @param enframe Whether to "enframe" the returned vector 17 | #' 18 | #' @name cooccurrence 19 | NULL 20 | 21 | #' @describeIn cooccurrence Adjacency matrix of the co-occurrence network 22 | #' @export 23 | cooccurrence_matrix <- function(mat, all = TRUE) { 24 | # To compute the number of times each pair of taxa cooccur, we leverage the 25 | # `compute_ratios()` function. Doing so requires that the samples (rows of 26 | # `mat`) and the taxa (cols of `mat`) have names. 27 | if (is.null(rownames(mat))) 28 | rownames(mat) <- paste0("S", seq(nrow(mat))) 29 | if (is.null(colnames(mat))) 30 | colnames(mat) <- paste0("T", seq(ncol(mat))) 31 | ratios <- mat %>% 32 | tibble::as_tibble(rownames = "Sample") %>% 33 | tidyr::gather("Taxon", "Value", -Sample) %>% 34 | compute_ratios() 35 | if (!all) { 36 | ratios <- dplyr::filter(ratios, !is.na(Value)) 37 | } 38 | adj_mat <- ratios %>% 39 | dplyr::filter(Taxon.x != Taxon.y) %>% 40 | dplyr::group_by(Taxon.x, Taxon.y) %>% 41 | dplyr::summarize(n = sum(!is.na(Value))) %>% 42 | dplyr::ungroup() %>% 43 | build_matrix(Taxon.x, Taxon.y, n, 0) 44 | adj_mat 45 | } 46 | 47 | #' @describeIn cooccurrence Co-occurrence network as an `igraph` object 48 | #' @export 49 | cooccurrence_network <- function(mat, all = TRUE) { 50 | adj_mat <- cooccurrence_matrix(mat, all = all) 51 | igraph::graph.adjacency(adj_mat, mode = "undirected", weighted = TRUE) 52 | } 53 | 54 | #' @describeIn cooccurrence Connected components of the co-occurrence network 55 | #' @export 56 | cooccurrence_components <- function(mat, all = TRUE, enframe = FALSE) { 57 | g <- cooccurrence_network(mat, all = all) 58 | components <- igraph::components(g)$membership 59 | 60 | if (enframe) 61 | components <- tibble::enframe(components, "Taxon", "Component") 62 | 63 | components 64 | } 65 | 66 | # TODO: Add example showing usage. Include plotting the graph with the edge 67 | # weights shown 68 | # TODO: Allow a matrix of the actual composition to be passed instead of the 69 | # error matrix 70 | -------------------------------------------------------------------------------- /R/calibrate.R: -------------------------------------------------------------------------------- 1 | # perturb --------------------------------------------------------------------- 2 | 3 | #' Compositionally perturb a relative-abundance matrix 4 | #' 5 | #' The perturbation of two compositional vectors `v` and `y` is given (up to 6 | #' compositional equivalence) by the elementwise product `v * y`. 7 | #' 8 | #' Let `w = v * y`, where `v` is a row or column of `x`. The normalization 9 | #' options specified by the `norm` argument are 10 | #' 11 | #' * "close" Return the compositional closure of w into the simplex, 12 | #' `w / sum(w)` 13 | #' * "keep" Keep the same total abundance as the original vector by returning 14 | #' `w * sum(v) / sum(w)` 15 | #' * "none" Return `w` without any normalization 16 | #' 17 | #' If `y` is named, then the names must agree with the taxa names in `x` and 18 | #' will be used to reorder `y` to match the taxa order in `x`. 19 | #' 20 | #' @param x An abundance matrix or phyloseq object containing one 21 | #' @param y A numeric vector with which to perturb the observations in x 22 | #' @param margin Matrix margin that corresponds to observations (samples); 23 | #' `1` for rows, `2` for columns 24 | #' @param norm String specifying how to normalize the perturbed observations; 25 | #' see Details. 26 | #' 27 | #' @seealso [calibrate()] 28 | #' 29 | #' @rdname perturb 30 | #' @export 31 | perturb <- function(x, y, ...) { 32 | UseMethod("perturb") 33 | } 34 | 35 | #' @rdname perturb 36 | #' @method perturb matrix 37 | #' @export 38 | perturb.matrix <- function(x, y, margin, norm = "close") { 39 | stopifnot(margin %in% 1:2) 40 | stopifnot(norm %in% c("close", "keep", "none")) 41 | taxa_margin <- setdiff(1:2, margin) 42 | stopifnot(identical(dim(x)[[taxa_margin]], length(y))) 43 | 44 | # Align taxa 45 | if (!is.null(names(y))) { 46 | if (!setequal(dimnames(x)[[taxa_margin]], names(y))) 47 | stop("Taxa names in `x` and `y` do not match") 48 | y <- y[dimnames(x)[[taxa_margin]]] 49 | } 50 | 51 | if (margin == 2) { 52 | z <- diag(y) %*% x 53 | rownames(z) <- rownames(x) 54 | if (norm %in% c("close", "keep")) 55 | z <- sweep(z, 2, colSums(z), `/`) 56 | if (norm == "keep") 57 | z <- sweep(z, 2, colSums(x), `*`) 58 | } else { 59 | z <- x %*% diag(y) 60 | colnames(z) <- colnames(x) 61 | if (norm %in% c("close", "keep")) 62 | z <- sweep(z, 1, rowSums(z), `/`) 63 | if (norm == "keep") 64 | z <- sweep(z, 1, rowSums(x), `*`) 65 | } 66 | 67 | z 68 | } 69 | 70 | #' @rdname perturb 71 | #' @method perturb otu_table 72 | #' @export 73 | perturb.otu_table <- function(x, y, norm = "close") { 74 | margin <- 1 + taxa_are_rows(x) 75 | z <- perturb.matrix(as(x, "matrix"), y, margin = margin, norm = norm) 76 | otu_table(z, taxa_are_rows = taxa_are_rows(x)) 77 | } 78 | 79 | #' @rdname perturb 80 | #' @method perturb phyloseq 81 | #' @export 82 | perturb.phyloseq <- function(x, y, norm = "close") { 83 | otu_table(x) <- perturb(otu_table(x), y, norm = norm) 84 | x 85 | } 86 | 87 | #' @rdname perturb 88 | #' @method perturb mc_bias_fit 89 | #' @export 90 | perturb.mc_bias_fit <- function(x, y) { 91 | stopifnot(identical(length(x$estimate), length(y))) 92 | x$estimate <- x$estimate * y 93 | if (!is.null(x$bootreps)) 94 | x$bootreps <- sweep(x$bootreps, 2, y, `*`) 95 | x 96 | } 97 | 98 | # calibrate ------------------------------------------------------------------- 99 | 100 | #' Calibrate a relative-abundance matrix by a bias vector 101 | #' 102 | #' Calibration via the simple deterministic procedure described in McLaren, 103 | #' Willis, and Callahan (2019), simply involved dividing the observed vector of 104 | #' relative abundances by the estimated bias vector and (optionally) 105 | #' normalizing the result to sum to 1 or some other chosen value. 106 | #' 107 | #' Normalization options specified by `norm`: 108 | #' 109 | #' * "close": Divide the calibrated abundance vector by its sum, so that it 110 | #' sums to 1 111 | #' * "keep": Keep the same total abundance as the original observation 112 | #' * "none": Return the calibrated abundances without any normalization 113 | #' 114 | #' If `bias` is named, then the names must agree with the taxa names in 115 | #' `observed` and will be used to reorder `bias` to match the taxa order in 116 | #' `observed`. 117 | #' 118 | #' @param observed An abundance matrix or phyloseq object containing one 119 | #' @param bias A numeric vector of relative efficiencies or an object of class 120 | #' 'mc_bias_fit' (from which efficiencies will be extracted) 121 | #' @param margin Matrix margin that corresponds to observations (samples); 122 | #' `1` for rows, `2` for columns 123 | #' @param norm String specifying how to normalize the calibrated observations; 124 | #' see Details. 125 | #' @param mean_name Character vector or NULL. Name of the column in the sample 126 | #' data in which to store the mean efficiency, or NULL to skip. 127 | #' 128 | #' @seealso [perturb()] [estimate_bias()] 129 | #' 130 | #' @rdname calibrate 131 | #' @export 132 | calibrate <- function(observed, bias, ...) { 133 | UseMethod("calibrate") 134 | } 135 | 136 | #' @rdname calibrate 137 | #' @method calibrate matrix 138 | #' @export 139 | calibrate.matrix <- function(observed, bias, margin, norm = "close") { 140 | if (inherits(bias, 'mc_bias_fit')) 141 | bias <- coef(bias) 142 | perturb.matrix(observed, 1 / bias, margin = margin, norm = norm) 143 | } 144 | 145 | #' @rdname calibrate 146 | #' @method calibrate otu_table 147 | #' @export 148 | calibrate.otu_table <- function(observed, bias, norm = "close") { 149 | if (inherits(bias, 'mc_bias_fit')) 150 | bias <- coef(bias) 151 | # The otu-table method will try to subset to the shared taxa in observed and 152 | # bias 153 | if (!identical(ntaxa(observed), length(bias))) { 154 | if (is.null(names(bias))) 155 | stop("`bias` must be named if `!identical(ntaxa(observed), length(bias))`") 156 | taxa <- intersect(taxa_names(observed), names(bias)) 157 | if (!length(taxa) > 0) 158 | stop("`intersect(taxa_names(observed), names(bias))` is empty") 159 | observed <- phyloseq::prune_taxa(taxa, observed) 160 | bias <- bias[taxa] 161 | } # else: perturb() will make sure the taxa names match the names in bias 162 | perturb.otu_table(observed, 1 / bias, norm = norm) 163 | } 164 | 165 | #' @rdname calibrate 166 | #' @method calibrate phyloseq 167 | #' @export 168 | calibrate.phyloseq <- function(observed, 169 | bias, 170 | norm = "close", 171 | mean_name = ".mean_efficiency") { 172 | otu_table(observed) <- calibrate(otu_table(observed), bias, norm = norm) 173 | if (!is.null(mean_name) & !is.null(phyloseq::access(observed, 'sam_data'))) { 174 | if (!is.character(mean_name)) 175 | stop('`mean_name` must be a character vector') 176 | me <- mean_efficiency( 177 | observed, 178 | bias, 179 | # `observed` is now calibrated so type = 'actual' 180 | type = 'actual' 181 | ) 182 | sample_data(observed)[, mean_name] <- me 183 | } 184 | observed 185 | } 186 | -------------------------------------------------------------------------------- /R/math.R: -------------------------------------------------------------------------------- 1 | # TODO 2 | # - check trim usage 3 | # - add documentation 4 | # - add tests 5 | 6 | # Element-wise functions ------------------------------------------------------ 7 | 8 | #' Odds of the probability vector x 9 | #' 10 | #' @export 11 | odds <- function (x) { 12 | x / (1-x) 13 | } 14 | 15 | #' Logit (log-odds) of the probability vector x 16 | #' 17 | #' @export 18 | logit <- function (x) { 19 | log(x) - log(1-x) 20 | } 21 | 22 | # Summaries of relative abundance vectors-------------------------------------- 23 | 24 | #' Geometric mean of x 25 | #' 26 | #' @export 27 | gm_mean <- function(x, na.rm = FALSE) { 28 | exp(mean(log(x), na.rm = na.rm)) 29 | } 30 | 31 | #' Geometric standard deviation of x 32 | #' 33 | #' Note, uses denominator n-1 34 | #' 35 | #' @export 36 | gm_sd <- function(x, na.rm = FALSE) { 37 | exp(sd(log(x), na.rm = na.rm)) 38 | } 39 | 40 | #' Geometric range of x 41 | #' 42 | #' @export 43 | gm_range <- function(x) { 44 | max(x) / min(x) 45 | } 46 | 47 | #' Geometric absolute value of x 48 | #' 49 | #' @export 50 | gm_abs <- function(x) { 51 | exp(abs(log(x))) 52 | } 53 | 54 | #' Geometric (multiplicative) version of the function f 55 | #' 56 | #' @export 57 | gm <- function(f) { 58 | function (x, ...) exp(f(log(x), ...)) 59 | } 60 | 61 | # Transformations for relative abundance vectors ------------------------------ 62 | 63 | #' Close the elements of x to proportions 64 | #' 65 | #' @export 66 | close_elts <- function (x, na.rm = FALSE) { 67 | x / sum(x, na.rm = na.rm) 68 | } 69 | 70 | #' Geometrically center the elements of x 71 | #' 72 | #' @export 73 | center_elts <- function (x, na.rm = FALSE) { 74 | exp(log(x) - mean(log(x), na.rm = na.rm)) 75 | } 76 | 77 | #' Compute the centered log-ratio transform of x 78 | #' 79 | #' @param x Vector of abundances. 80 | #' @param base Base for logarithm 81 | #' 82 | #' @export 83 | clr <- function(x, base = exp(1), na.rm = FALSE) { 84 | log(x, base = base) - mean(log(x, base = base), na.rm = na.rm) 85 | } 86 | 87 | # Distance / dissimilarity between samples ------------------------------------ 88 | 89 | #' Distance or dissimilarity between relative abundance vectors x and y 90 | #' 91 | #' @param method Distance/dissimilarity measure. 92 | #' @param trim Should x and y be reduced to their common positive elements 93 | #' before computing the Aitchison distance (otherwise, the distance will be 94 | #' Inf). 95 | #' 96 | #' method == "aitchison" -> Aitchison distance 97 | #' method == "bray" -> Bray-Curtis dissimilarity between x and y. Note, 98 | #' converts x and y to proportions before computing. 99 | #' 100 | #' @export 101 | # Bray method is equal to `vegan::vegdist(rbind(close_elts(x), close_elts(y)))[1]` 102 | xydist <- function(x, y, method = "aitchison", trim = FALSE) { 103 | if (length(x) != length(y)) { 104 | stop("x and y have different lengths") 105 | } 106 | if (method == "aitchison") { 107 | if (trim) { 108 | idx <- (x > 0) & (y > 0) 109 | x <- x[idx] 110 | y <- y[idx] 111 | } 112 | sqrt( sum( (clr(x) - clr(y))^2 ) ) 113 | } else if (method == "bray") { 114 | x <- close_elts(x) 115 | y <- close_elts(y) 116 | Cxy <- purrr::map2_dbl(x, y, min) %>% sum 117 | 1 - Cxy 118 | } 119 | } 120 | 121 | #' Aitchison norm of x 122 | #' 123 | #' @param na.rm Whether to remove NAs and NaNs before calculating. 124 | #' 125 | #' @export 126 | anorm <- function (x, na.rm = FALSE) { 127 | x %>% 128 | clr(., na.rm = na.rm) %>% 129 | {.^2} %>% 130 | sum(., na.rm = na.rm) %>% 131 | sqrt(.) 132 | } 133 | -------------------------------------------------------------------------------- /R/mean_efficiency.R: -------------------------------------------------------------------------------- 1 | #' Compute sample mean efficiencies 2 | #' 3 | #' Given a matrix of 'observed' or 'actual' (e.g. calibrated) abundance 4 | #' profiles and a vector of relative efficiencies, compute the estimated mean 5 | #' efficiency for each sample. 6 | #' 7 | #' The mean efficiency of a sample equals `weighted.mean(bias, y)`, where 8 | #' `bias` is the vector of taxa efficiencies and `y` is the vector of taxa 9 | #' proportions. 10 | #' 11 | #' The `type %in% c('actual', 'observed')` specifies whether the data is 12 | #' 'actual' (i.e. nominally known or calibrated abundances) or 'observed' (i.e. 13 | #' uncalibrated) data. 'Observed' data is calibrated to determine `y` prior to 14 | #' computing the mean efficiency. 15 | #' 16 | #' If `x` is an `mc_bias_fit` object, then the efficiencies will be extracted 17 | #' with `coef(x)`. An abundance matrix can optionally be given with `newdata`; 18 | #' otherwise, the mean efficiency will be computed for the control samples in 19 | #' `x`. 20 | #' 21 | #' `r lifecycle::badge("experimental")` 22 | #' 23 | #' @param x A matrix, a phyloseq object with an otu_table, or an object of 24 | #' class 'mc_bias_fit' 25 | #' @param bias A (possibly named) numeric vector of relative efficiencies 26 | #' @param newdata NULL or an abundance matrix 27 | #' @param margin The margin containing the samples (observations) 28 | #' @param type 'actual' or 'observed', indicating the type of abundance 29 | #' profiles in the matrix `x` or `newdata` 30 | #' 31 | #' @seealso [estimate_bias()] 32 | #' 33 | #' @rdname mean_efficiency 34 | #' @export 35 | # mean_efficiency <- function(bias, actual, observed, margin) { 36 | # UseMethod("mean_efficiency") 37 | # } 38 | mean_efficiency <- function(x, ...) { 39 | UseMethod("mean_efficiency") 40 | } 41 | 42 | #' @rdname mean_efficiency 43 | #' @method mean_efficiency matrix 44 | #' @export 45 | mean_efficiency.matrix <- function(x, 46 | bias, 47 | margin, 48 | type) { 49 | # First, get to point where `x` is a matrix with the 'actual' (unbiased) 50 | # profiles with samples as rows, and the taxa (columns) are properly aligned 51 | # with `bias`. 52 | if (!margin %in% 1:2) 53 | stop("`margin` must be 1 or 2.") 54 | if (margin == 2) { 55 | x <- t(x) 56 | margin <- 1 57 | } 58 | taxa_margin <- 2 59 | if (type == 'observed') { 60 | # Note: Consider allowing taxa to be dropped from 'observed' with a 61 | # message, in the case where 'bias' is named. 62 | stopifnot(identical(dim(x)[[taxa_margin]], length(bias))) 63 | x <- calibrate(x, bias, margin = margin, norm = 'none') 64 | } else if (type != 'actual') { 65 | stop("`type` must be 'actual' or 'observed'.") 66 | } 67 | # TODO: Add ability to extract efficiencies from mc_bias_fit objects 68 | # Align taxa order between x and bias 69 | if (!is.null(names(bias))) { 70 | if (!setequal(dimnames(x)[[taxa_margin]], names(bias))) 71 | stop("Taxa names in `bias` and `actual` do not match") 72 | bias <- bias[dimnames(x)[[taxa_margin]]] 73 | } 74 | 75 | # Can also do the same thing slightly slower with weighted.mean() 76 | # apply(bias$actual, 1, function(x) weighted.mean(bias, x)) 77 | 78 | x %>% 79 | # normalize to proportions 80 | sweep(., 1, rowSums(.), `/`) %>% 81 | # multiply taxa by their efficiency 82 | perturb(bias, margin = 1, norm = 'none') %>% 83 | # sum up within samples 84 | rowSums 85 | } 86 | 87 | #' @rdname mean_efficiency 88 | #' @method mean_efficiency otu_table 89 | #' @export 90 | mean_efficiency.otu_table <- function(x, bias, type) { 91 | mean_efficiency( 92 | as(x, "matrix"), 93 | bias, 94 | margin = 1 + taxa_are_rows(x), 95 | type = type 96 | ) 97 | } 98 | 99 | #' @rdname mean_efficiency 100 | #' @method mean_efficiency phyloseq 101 | #' @export 102 | mean_efficiency.phyloseq <- function(x, bias, type) { 103 | mean_efficiency(otu_table(x), bias, type = type) 104 | } 105 | 106 | #' @rdname mean_efficiency 107 | #' @method mean_efficiency mc_bias_fit 108 | #' @export 109 | mean_efficiency.mc_bias_fit <- function(x, 110 | newdata = NULL, 111 | margin = NULL, 112 | type = NULL) { 113 | bias = coef(x) 114 | 115 | if (is.null(newdata)) { 116 | stopifnot(is.null(margin)) 117 | x <- x$actual 118 | type <- 'actual' 119 | margin <- 1 120 | } else { 121 | if (! type %in% c('actual', 'observed')) { 122 | stop("`type` must be 'actual' or 'observed'.") 123 | } 124 | if (! margin %in% 1:2) { 125 | stop("`margin` must be 1 or 2.") 126 | } 127 | } 128 | 129 | mean_efficiency( 130 | x = x, 131 | bias = bias, 132 | type = type, 133 | margin = margin 134 | ) 135 | } 136 | 137 | -------------------------------------------------------------------------------- /R/metacal-package.R: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | 4 | ## usethis namespace: start 5 | ## usethis namespace: end 6 | NULL 7 | -------------------------------------------------------------------------------- /R/metacal.R: -------------------------------------------------------------------------------- 1 | #' Import phyloseq classes and functions 2 | #' 3 | #' @name import_phyloseq 4 | #' @importClassesFrom phyloseq otu_table phyloseq 5 | #' @importFrom phyloseq otu_table otu_table<- t taxa_are_rows taxa_names 6 | #' sample_names ntaxa nsamples sample_sums prune_taxa 7 | #' sample_data sample_data<- 8 | NULL 9 | -------------------------------------------------------------------------------- /R/utilities.R: -------------------------------------------------------------------------------- 1 | #' @name corner 2 | #' @importFrom useful corner 3 | #' @export 4 | useful::corner 5 | 6 | # Helpers for working with "tidy" microbiome data ----------------------------- 7 | 8 | #' Mutate within groups 9 | #' 10 | #' @export 11 | mutate_by <- function(.data, group_vars, ...) { 12 | gvs <- rlang::enquos(group_vars) 13 | .data %>% 14 | dplyr::group_by_at(vars(!!!gvs)) %>% 15 | dplyr::mutate(...) %>% 16 | dplyr::ungroup() 17 | } 18 | 19 | #' Create a matrix from columns of a tidy data frame 20 | #' 21 | #' Note: Setting `fill` will replace NAs and NaNs, along with elements 22 | #' corresponding to missing rows, with the value of `fill`. 23 | #' 24 | #' @param .data A data frame with columns `rows`, `cols`, and `elts`. 25 | #' @param rows Column that will become the rownames of the matrix. 26 | #' @param cols Column that will become the colnames of the matrix. 27 | #' @param elts Column that will become the matrix elements. 28 | #' @param fill Value to use for missing elements. 29 | #' @export 30 | build_matrix <- function(.data, rows, cols, elts, fill = NULL) { 31 | rows <- rlang::enquo(rows) 32 | cols <- rlang::enquo(cols) 33 | elts <- rlang::enquo(elts) 34 | tb <- .data %>% 35 | dplyr::ungroup() %>% 36 | dplyr::select(!!rows, !!cols, !!elts) 37 | if (!is.null(fill)) { 38 | tb <- tb %>% tidyr::complete(!!rows, !!cols, 39 | fill = rlang::list2(!!elts := fill)) 40 | } 41 | tb <- tb %>% tidyr::pivot_wider(names_from = !!cols, values_from = !!elts) 42 | mat <- tb %>% dplyr::select(-!!rows) %>% as("matrix") 43 | rownames(mat) <- tb %>% dplyr::pull(!!rows) 44 | mat 45 | } 46 | 47 | #' Coerce a (wide) data frame to a matrix 48 | #' 49 | #' @export 50 | as_matrix <- function(.data, rownames = NULL) { 51 | rownames <- rlang::enquo(rownames) 52 | if (rlang::quo_is_null(rownames)) { 53 | mat <- .data %>% as("matrix") 54 | } else { 55 | mat <- .data %>% dplyr::select(-!!rownames) %>% as("matrix") 56 | rownames(mat) <- .data %>% dplyr::pull(!!rownames) 57 | } 58 | mat 59 | } 60 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | # Import magrittr pipe for internal use 2 | 3 | #' @importFrom magrittr %>% 4 | NULL 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # metacal 2 | 3 | [![DOI](https://zenodo.org/badge/192036279.svg)](https://zenodo.org/badge/latestdoi/192036279) 4 | 5 | The metacal package provides tools for bias estimation and calibration in 6 | marker-gene and metagenomics sequencing experiments. It implements the methods 7 | described in [McLaren MR, Willis AD, Callahan BJ 8 | (2019)](https://elifesciences.org/articles/46923) and is used for the 9 | analysis associated with that manuscript, available at the [manuscript's 10 | repository](https://github.com/mikemc/mgs-bias-manuscript). 11 | 12 | ## Installation 13 | 14 | Install the development version of metacal from from GitHub, 15 | 16 | ``` r 17 | # install.packages("devtools") 18 | devtools::install_github("mikemc/metacal") 19 | ``` 20 | 21 | ## Usage 22 | 23 | See the [package tutorial](https://mikemc.github.io/metacal/articles/tutorial.html) 24 | for a demonstration of how to estimate bias from control samples with known 25 | composition (i.e., mock community samples), and how to calibrate the relative 26 | abundances in unknown samples of the taxa that were in the controls. 27 | 28 | The primary utility of this package is quantitatively estimating the bias of 29 | protocols in quality control experiments, where samples with known composition 30 | are measured or samples with unknown composition are measured by multiple 31 | protocols. 32 | 33 | It is currently not possible to calibrate the composition of a natural 34 | community without making strong and untested assumptions about bias being the 35 | same for constructed and natural samples and about the efficiencies of taxa not 36 | in the controls (e.g., approximating them by that of the closest relative or 37 | the average efficiency). For this and other limitations described in the 38 | Discussion of our manuscript, calibration as a practical method to obtain 39 | quantitatively accurate composition measurements is not currently feasible 40 | using this or any package. However, calibration using a hypothesized bias 41 | (perhaps partially informed by experimental measurement) can still be useful to 42 | analyze the sensitivity of downstream results to bias, a use case we will 43 | illustrate in a future vignette. 44 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | reference: 2 | - title: Bias estimation and calibration 3 | - contents: 4 | - estimate_bias 5 | - calibrate 6 | - starts_with("cooccurrence") 7 | - title: Compositional-data computations 8 | - contents: 9 | - perturb 10 | - pairwise_ratios 11 | - compute_ratios 12 | - center 13 | - bootrep_center 14 | - center_elts 15 | - close_elts 16 | - clr 17 | - logit 18 | - odds 19 | - anorm 20 | - xydist 21 | - starts_with("gm") 22 | - title: Data-frame manipulation and coercion 23 | - contents: 24 | - as_matrix 25 | - build_matrix 26 | - mutate_by 27 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Page not found (404) • metacal 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 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 | Content not found. Please use links in the navbar. 129 | 130 |
131 | 132 | 137 | 138 |
139 | 140 | 141 | 142 | 152 |
153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /docs/LICENSE-text.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | License • metacal 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 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 |
YEAR: 2019
129 | COPYRIGHT HOLDER: Michael R. McLaren
130 | 
131 | 132 |
133 | 134 | 139 | 140 |
141 | 142 | 143 | 144 | 154 |
155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /docs/LICENSE.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | MIT License • metacal 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 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 |
129 | 130 |

Copyright (c) 2019 Michael R. McLaren

131 |

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

132 |

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

133 |

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

134 |
135 | 136 |
137 | 138 | 143 | 144 |
145 | 146 | 147 | 148 | 158 |
159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Articles • metacal 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 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 |
129 |

All vignettes

130 |

131 | 132 |
133 |
Tutorial
134 |
135 |
136 |
137 |
138 |
139 | 140 | 141 | 151 |
152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /docs/articles/tutorial_files/figure-html/unnamed-chunk-11-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemc/metacal/f56792d02bd722ab16c1ed215b07c1187829a226/docs/articles/tutorial_files/figure-html/unnamed-chunk-11-1.png -------------------------------------------------------------------------------- /docs/articles/tutorial_files/figure-html/unnamed-chunk-17-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemc/metacal/f56792d02bd722ab16c1ed215b07c1187829a226/docs/articles/tutorial_files/figure-html/unnamed-chunk-17-1.png -------------------------------------------------------------------------------- /docs/articles/tutorial_files/figure-html/unnamed-chunk-20-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemc/metacal/f56792d02bd722ab16c1ed215b07c1187829a226/docs/articles/tutorial_files/figure-html/unnamed-chunk-20-1.png -------------------------------------------------------------------------------- /docs/articles/tutorial_files/figure-html/unnamed-chunk-23-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemc/metacal/f56792d02bd722ab16c1ed215b07c1187829a226/docs/articles/tutorial_files/figure-html/unnamed-chunk-23-1.png -------------------------------------------------------------------------------- /docs/articles/tutorial_files/figure-html/unnamed-chunk-24-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemc/metacal/f56792d02bd722ab16c1ed215b07c1187829a226/docs/articles/tutorial_files/figure-html/unnamed-chunk-24-1.png -------------------------------------------------------------------------------- /docs/articles/tutorial_files/figure-html/unnamed-chunk-8-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemc/metacal/f56792d02bd722ab16c1ed215b07c1187829a226/docs/articles/tutorial_files/figure-html/unnamed-chunk-8-1.png -------------------------------------------------------------------------------- /docs/articles/tutorial_files/header-attrs-2.9/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Authors • metacal 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 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 |
    129 |
  • 130 |

    Michael McLaren. Author, maintainer. 131 |

    132 |
  • 133 |
134 | 135 |
136 | 137 |
138 | 139 | 140 | 141 | 151 |
152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('.navbar-fixed-top').headroom(); 6 | 7 | $('body').css('padding-top', $('.navbar').height() + 10); 8 | $(window).resize(function(){ 9 | $('body').css('padding-top', $('.navbar').height() + 10); 10 | }); 11 | 12 | $('[data-toggle="tooltip"]').tooltip(); 13 | 14 | var cur_path = paths(location.pathname); 15 | var links = $("#navbar ul li a"); 16 | var max_length = -1; 17 | var pos = -1; 18 | for (var i = 0; i < links.length; i++) { 19 | if (links[i].getAttribute("href") === "#") 20 | continue; 21 | // Ignore external links 22 | if (links[i].host !== location.host) 23 | continue; 24 | 25 | var nav_path = paths(links[i].pathname); 26 | 27 | var length = prefix_length(nav_path, cur_path); 28 | if (length > max_length) { 29 | max_length = length; 30 | pos = i; 31 | } 32 | } 33 | 34 | // Add class to parent
  • , and enclosing
  • if in dropdown 35 | if (pos >= 0) { 36 | var menu_anchor = $(links[pos]); 37 | menu_anchor.parent().addClass("active"); 38 | menu_anchor.closest("li.dropdown").addClass("active"); 39 | } 40 | }); 41 | 42 | function paths(pathname) { 43 | var pieces = pathname.split("/"); 44 | pieces.shift(); // always starts with / 45 | 46 | var end = pieces[pieces.length - 1]; 47 | if (end === "index.html" || end === "") 48 | pieces.pop(); 49 | return(pieces); 50 | } 51 | 52 | // Returns -1 if not found 53 | function prefix_length(needle, haystack) { 54 | if (needle.length > haystack.length) 55 | return(-1); 56 | 57 | // Special case for length-0 haystack, since for loop won't run 58 | if (haystack.length === 0) { 59 | return(needle.length === 0 ? 0 : -1); 60 | } 61 | 62 | for (var i = 0; i < haystack.length; i++) { 63 | if (needle[i] != haystack[i]) 64 | return(i); 65 | } 66 | 67 | return(haystack.length); 68 | } 69 | 70 | /* Clipboard --------------------------*/ 71 | 72 | function changeTooltipMessage(element, msg) { 73 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 74 | element.setAttribute('data-original-title', msg); 75 | $(element).tooltip('show'); 76 | element.setAttribute('data-original-title', tooltipOriginalTitle); 77 | } 78 | 79 | if(ClipboardJS.isSupported()) { 80 | $(document).ready(function() { 81 | var copyButton = ""; 82 | 83 | $(".examples, div.sourceCode").addClass("hasCopyButton"); 84 | 85 | // Insert copy buttons: 86 | $(copyButton).prependTo(".hasCopyButton"); 87 | 88 | // Initialize tooltips: 89 | $('.btn-copy-ex').tooltip({container: 'body'}); 90 | 91 | // Initialize clipboard: 92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 93 | text: function(trigger) { 94 | return trigger.parentNode.textContent; 95 | } 96 | }); 97 | 98 | clipboardBtnCopies.on('success', function(e) { 99 | changeTooltipMessage(e.trigger, 'Copied!'); 100 | e.clearSelection(); 101 | }); 102 | 103 | clipboardBtnCopies.on('error', function() { 104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 105 | }); 106 | }); 107 | } 108 | })(window.jQuery || window.$) 109 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 2.14.0.2 2 | pkgdown: 1.6.1 3 | pkgdown_sha: ~ 4 | articles: 5 | tutorial: tutorial.html 6 | last_built: 2021-07-31T14:34Z 7 | 8 | -------------------------------------------------------------------------------- /docs/reference/Rplot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikemc/metacal/f56792d02bd722ab16c1ed215b07c1187829a226/docs/reference/Rplot001.png -------------------------------------------------------------------------------- /docs/reference/anorm.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Aitchison norm of x — anorm • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Aitchison norm of x

    133 |
    134 | 135 |
    anorm(x, na.rm = FALSE)
    136 | 137 |

    Arguments

    138 | 139 | 140 | 141 | 142 | 143 | 144 |
    na.rm

    Whether to remove NAs and NaNs before calculating.

    145 | 146 | 147 |
    148 | 153 |
    154 | 155 | 156 |
    157 | 160 | 161 |
    162 |

    Site built with pkgdown 1.6.1.

    163 |
    164 | 165 |
    166 |
    167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /docs/reference/as_matrix.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Coerce a (wide) data frame to a matrix — as_matrix • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Coerce a (wide) data frame to a matrix

    133 |
    134 | 135 |
    as_matrix(.data, rownames = NULL)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/center_elts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Geometrically center the elements of x — center_elts • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Geometrically center the elements of x

    133 |
    134 | 135 |
    center_elts(x, na.rm = FALSE)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/close_elts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Close the elements of x to proportions — close_elts • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Close the elements of x to proportions

    133 |
    134 | 135 |
    close_elts(x, na.rm = FALSE)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/corner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Objects exported from other packages — corner • metacal 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 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
    68 |
    69 | 123 | 124 | 125 | 126 |
    127 | 128 |
    129 |
    130 | 135 | 136 |
    137 |

    These objects are imported from other packages. Follow the links 138 | below to see their documentation.

    139 |
    140 |
    useful

    corner

    141 | 142 |
    143 |
    144 | 145 | 146 | 147 | 148 |
    149 | 154 |
    155 | 156 | 157 |
    158 | 161 | 162 |
    163 |

    Site built with pkgdown 1.6.1.

    164 |
    165 | 166 |
    167 |
    168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /docs/reference/gm.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Geometric (multiplicative) version of the function f — gm • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Geometric (multiplicative) version of the function f

    133 |
    134 | 135 |
    gm(f)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/gm_abs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Geometric absolute value of x — gm_abs • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Geometric absolute value of x

    133 |
    134 | 135 |
    gm_abs(x)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/gm_mean.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Geometric mean of x — gm_mean • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Geometric mean of x

    133 |
    134 | 135 |
    gm_mean(x, na.rm = FALSE)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/gm_range.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Geometric range of x — gm_range • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Geometric range of x

    133 |
    134 | 135 |
    gm_range(x)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/gm_sd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Geometric standard deviation of x — gm_sd • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Note, uses denominator n-1

    133 |
    134 | 135 |
    gm_sd(x, na.rm = FALSE)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/import_phyloseq.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Import phyloseq classes and functions — import_phyloseq • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Import phyloseq classes and functions

    133 |
    134 | 135 | 136 | 137 | 138 |
    139 | 144 |
    145 | 146 | 147 |
    148 | 151 | 152 |
    153 |

    Site built with pkgdown 1.6.1.

    154 |
    155 | 156 |
    157 |
    158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /docs/reference/logit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Logit (log-odds) of the probability vector x — logit • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Logit (log-odds) of the probability vector x

    133 |
    134 | 135 |
    logit(x)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/mutate_by.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Mutate within groups — mutate_by • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Mutate within groups

    133 |
    134 | 135 |
    mutate_by(.data, group_vars, ...)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 |
    149 | 152 | 153 |
    154 |

    Site built with pkgdown 1.6.1.

    155 |
    156 | 157 |
    158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/reference/odds.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Odds of the probability vector x — odds • metacal 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 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    Odds of the probability vector x

    133 |
    134 | 135 |
    odds(x)
    136 | 137 | 138 | 139 |
    140 | 145 |
    146 | 147 | 148 | 158 |
    159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /inst/extdata/brooks2015-actual.csv: -------------------------------------------------------------------------------- 1 | Sample,Atopobium_vaginae,Gardnerella_vaginalis,Lactobacillus_crispatus,Lactobacillus_iners,Prevotella_bivia,Sneathia_amnii,Streptococcus_agalactiae 2 | s1-1,0,0,0.3333333333333333,0,0.3333333333333333,0,0.3333333333333333 3 | s1-10,0.3333333333333333,0,0.3333333333333333,0,0,0.3333333333333333,0 4 | s1-11,0,0.3333333333333333,0.3333333333333333,0.3333333333333333,0,0,0 5 | s1-12,0.5,0,0,0,0.5,0,0 6 | s1-13,0,0,0.3333333333333333,0,0.3333333333333333,0.3333333333333333,0 7 | s1-14,0,0,0.5,0,0,0,0.5 8 | s1-15,0.3333333333333333,0,0,0.3333333333333333,0,0,0.3333333333333333 9 | s1-16,0,0,0,0.5,0,0.5,0 10 | s1-17,0,0,0,0,0,0,1 11 | s1-18,0,0.5,0.5,0,0,0,0 12 | s1-19,0,0,0,0.3333333333333333,0.3333333333333333,0,0.3333333333333333 13 | s1-2,0.3333333333333333,0.3333333333333333,0.3333333333333333,0,0,0,0 14 | s1-20,0,0,0,0,0.5,0,0.5 15 | s1-21,0.3333333333333333,0,0,0,0.3333333333333333,0,0.3333333333333333 16 | s1-22,0.3333333333333333,0,0,0.3333333333333333,0,0.3333333333333333,0 17 | s1-23,0.14285714285714285,0.14285714285714285,0.14285714285714285,0.14285714285714285,0.14285714285714285,0.14285714285714285,0.14285714285714285 18 | s1-24,0,0.3333333333333333,0,0,0,0.3333333333333333,0.3333333333333333 19 | s1-25,0,0.3333333333333333,0,0.3333333333333333,0,0,0.3333333333333333 20 | s1-26,0,0.3333333333333333,0,0,0.3333333333333333,0,0.3333333333333333 21 | s1-27,0,0.3333333333333333,0.3333333333333333,0,0.3333333333333333,0,0 22 | s1-28,0,0,1,0,0,0,0 23 | s1-29,0,0.5,0,0,0,0.5,0 24 | s1-3,0.3333333333333333,0.3333333333333333,0,0,0.3333333333333333,0,0 25 | s1-30,0,0.3333333333333333,0.3333333333333333,0,0,0.3333333333333333,0 26 | s1-31,0,0,0,0.5,0.5,0,0 27 | s1-32,0.5,0,0.5,0,0,0,0 28 | s1-33,0,0,0.5,0.5,0,0,0 29 | s1-34,1,0,0,0,0,0,0 30 | s1-35,0,0.25,0,0.25,0.25,0.25,0 31 | s1-36,0,0,0,0.3333333333333333,0,0.3333333333333333,0.3333333333333333 32 | s1-37,0.3333333333333333,0.3333333333333333,0,0,0,0,0.3333333333333333 33 | s1-38,0,0,0,0,0.5,0.5,0 34 | s1-39,0,0.5,0,0.5,0,0,0 35 | s1-4,0.3333333333333333,0,0.3333333333333333,0,0,0,0.3333333333333333 36 | s1-40,0,0,0.5,0,0,0.5,0 37 | s1-5,0,0.5,0,0,0.5,0,0 38 | s1-6,0.3333333333333333,0,0,0.3333333333333333,0.3333333333333333,0,0 39 | s1-7,0.5,0,0,0,0,0,0.5 40 | s1-8,0,0.5,0,0,0,0,0.5 41 | s1-9,0.3333333333333333,0,0,0,0,0.3333333333333333,0.3333333333333333 42 | s2-1,0,0,0,0,0,0,1 43 | s2-10,0,0,0,0,0,1,0 44 | s2-11,0,0.3333333333333333,0.3333333333333333,0,0,0,0.3333333333333333 45 | s2-12,0.3333333333333333,0.3333333333333333,0,0,0,0,0.3333333333333333 46 | s2-13,0.3333333333333333,0,0.3333333333333333,0,0.3333333333333333,0,0 47 | s2-14,0.14285714285714285,0.14285714285714285,0.14285714285714285,0.14285714285714285,0.14285714285714285,0.14285714285714285,0.14285714285714285 48 | s2-15,0,0,0,0,0.3333333333333333,0.3333333333333333,0.3333333333333333 49 | s2-16,0,0,0.3333333333333333,0.3333333333333333,0,0,0.3333333333333333 50 | s2-17,0.3333333333333333,0.3333333333333333,0,0.3333333333333333,0,0,0 51 | s2-18,1,0,0,0,0,0,0 52 | s2-19,0,0,0.5,0.5,0,0,0 53 | s2-2,0,0,0.3333333333333333,0,0,0.3333333333333333,0.3333333333333333 54 | s2-20,0.3333333333333333,0.3333333333333333,0.3333333333333333,0,0,0,0 55 | s2-21,0,0,0.5,0,0,0,0.5 56 | s2-22,0,0,0,0,1,0,0 57 | s2-23,0.5,0,0,0,0.5,0,0 58 | s2-24,0,0,0,1,0,0,0 59 | s2-25,0,0,0,0.3333333333333333,0,0.3333333333333333,0.3333333333333333 60 | s2-26,0,0,0.3333333333333333,0.3333333333333333,0.3333333333333333,0,0 61 | s2-27,0.3333333333333333,0,0,0.3333333333333333,0,0,0.3333333333333333 62 | s2-28,0,0,0.5,0,0.5,0,0 63 | s2-29,0,0,0,0.5,0,0,0.5 64 | s2-3,0,0.3333333333333333,0,0,0,0.3333333333333333,0.3333333333333333 65 | s2-30,0,0,0.5,0,0,0.5,0 66 | s2-31,0.3333333333333333,0,0.3333333333333333,0,0,0.3333333333333333,0 67 | s2-32,0,0,0,0.3333333333333333,0.3333333333333333,0.3333333333333333,0 68 | s2-33,0,0,0,0,0,0.5,0.5 69 | s2-34,0.3333333333333333,0,0,0,0.3333333333333333,0.3333333333333333,0 70 | s2-35,0.3333333333333333,0,0.3333333333333333,0.3333333333333333,0,0,0 71 | s2-36,0,0.3333333333333333,0,0,0.3333333333333333,0.3333333333333333,0 72 | s2-37,0,1,0,0,0,0,0 73 | s2-38,0,0.3333333333333333,0,0.3333333333333333,0,0.3333333333333333,0 74 | s2-39,0.5,0.5,0,0,0,0,0 75 | s2-4,0.5,0,0,0,0,0.5,0 76 | s2-40,0,0,0.3333333333333333,0.3333333333333333,0,0.3333333333333333,0 77 | s2-5,0.5,0,0,0.5,0,0,0 78 | s2-6,0.3333333333333333,0.3333333333333333,0,0,0,0.3333333333333333,0 79 | s2-7,0,0,0,0.3333333333333333,0.3333333333333333,0,0.3333333333333333 80 | s2-8,0,0.3333333333333333,0,0.3333333333333333,0.3333333333333333,0,0 81 | s2-9,0,0.3333333333333333,0.3333333333333333,0,0.3333333333333333,0,0 82 | -------------------------------------------------------------------------------- /inst/extdata/brooks2015-observed.csv: -------------------------------------------------------------------------------- 1 | Sample,Atopobium_vaginae,Gardnerella_vaginalis,Lactobacillus_crispatus,Lactobacillus_iners,Prevotella_bivia,Sneathia_amnii,Streptococcus_agalactiae,Other 2 | s1-1,1,1,13670,0,7544,1,1506,7 3 | s1-10,1028,0,10310,2,1,14947,2,3 4 | s1-11,0,181,3956,7598,6,2,0,2 5 | s1-12,1424,0,0,1,21708,7,0,8 6 | s1-13,0,0,3199,0,1854,6501,0,3 7 | s1-14,0,0,9348,2,0,3,1475,10 8 | s1-15,572,0,1,7493,1,3,466,4 9 | s1-16,0,0,1,3849,0,3590,4,2 10 | s1-17,2,1,19,4,1,14,51332,206 11 | s1-18,0,865,9892,0,0,0,0,7 12 | s1-19,0,0,0,9138,4339,2,468,3 13 | s1-2,2930,1650,22645,0,1,1,4,8 14 | s1-20,0,0,4,5,16249,5,1937,6 15 | s1-21,1232,0,1,3,9639,2,1249,5 16 | s1-22,361,0,0,7117,0,6229,1,0 17 | s1-23,351,203,2463,4886,1460,4798,281,1 18 | s1-24,1,621,0,1,2,16454,906,1 19 | s1-25,0,787,4,21869,0,355,1100,2 20 | s1-26,0,1007,3,1,10761,0,1217,3 21 | s1-27,0,522,9194,1,5792,3,2,6 22 | s1-28,0,0,21759,0,1,7,1,5 23 | s1-29,2,1020,1,1,0,23306,0,11 24 | s1-3,2073,1514,3,1,15772,0,1,16 25 | s1-30,1,283,4740,4,0,12702,0,2 26 | s1-31,1,0,6,8471,3555,0,2,0 27 | s1-32,1172,0,9825,0,0,1,1,1 28 | s1-33,3,0,4192,9087,0,0,1,2 29 | s1-34,13370,0,0,3,2,4,0,18 30 | s1-35,1,267,0,8329,3190,5445,5,1 31 | s1-36,1,0,0,5821,1,6622,308,0 32 | s1-37,5493,2422,0,2,0,1,4971,20 33 | s1-38,3,1,0,3,4677,9272,0,0 34 | s1-39,1,275,3,8890,0,1,0,0 35 | s1-4,2217,0,16037,0,5,30,1557,8 36 | s1-40,1,0,2292,0,0,5974,0,1 37 | s1-5,0,754,3,0,14670,3,0,5 38 | s1-6,500,1,2,9866,4318,0,0,2 39 | s1-7,7782,1,0,0,0,0,6678,14 40 | s1-8,2,3307,0,0,3,2,3252,13 41 | s1-9,1403,0,0,0,0,15119,1085,6 42 | s2-1,0,0,176,9,2,15,24437,6 43 | s2-10,1,0,1,2,0,22682,1,1 44 | s2-11,0,570,10690,3,0,3,1143,4 45 | s2-12,7170,2642,7,7,0,47,9387,45 46 | s2-13,1245,3,11969,18,7303,1,1,1 47 | s2-14,511,308,2256,4175,1648,4707,259,2 48 | s2-15,0,0,0,4,5126,13714,649,1 49 | s2-16,0,0,4288,8703,0,0,533,4 50 | s2-17,837,523,0,13121,0,0,0,4 51 | s2-18,12395,0,2,2,0,124,1,18 52 | s2-19,0,0,3427,7517,0,1,0,1 53 | s2-2,0,0,6497,1,0,11854,679,2 54 | s2-20,1730,956,11699,5,1,4,6,2 55 | s2-21,0,3,10777,3,4,0,1160,1 56 | s2-22,0,0,3,3,15696,1,0,0 57 | s2-23,2261,0,1,0,12096,0,6,2 58 | s2-24,0,0,0,14783,0,2,0,0 59 | s2-25,2,2,3,12498,0,13504,733,0 60 | s2-26,0,0,4775,11234,3249,1,0,5 61 | s2-27,424,0,0,7120,0,1,447,6 62 | s2-28,0,1,10682,0,7253,1,1,2 63 | s2-29,2,0,3,15628,1,4,771,3 64 | s2-3,1,714,2,1,0,19831,924,4 65 | s2-30,0,0,6294,3,0,17503,0,6 66 | s2-31,615,2,4552,7,3,9467,1,1 67 | s2-32,1,0,0,10509,3685,10047,0,3 68 | s2-33,0,0,4,10,1,24914,1189,5 69 | s2-34,569,0,0,1,4261,12493,0,1 70 | s2-35,441,0,3461,7611,1,7,0,0 71 | s2-36,0,232,0,7,2532,10118,0,0 72 | s2-37,0,4770,5,7,0,0,1,9 73 | s2-38,0,192,0,6962,1,6399,0,0 74 | s2-39,14324,8200,4,4,35,5,1,23 75 | s2-4,1449,0,14,9,6,20636,0,0 76 | s2-40,0,0,2286,5677,0,6239,0,3 77 | s2-5,883,0,0,14212,7,11,0,2 78 | s2-6,1533,1021,12,1,1,17227,1,4 79 | s2-7,0,0,1,12725,4926,3,663,4 80 | s2-8,0,746,3,20551,7766,2,0,4 81 | s2-9,0,491,9872,0,6410,0,0,10 82 | -------------------------------------------------------------------------------- /inst/extdata/brooks2015-sample-data.csv: -------------------------------------------------------------------------------- 1 | Sample,Plate,Barcode,Mixture_type,Num_species,Species_list 2 | s1-1,1,1,Cells,3,Lactobacillus_crispatus;Prevotella_bivia;Streptococcus_agalactiae 3 | s1-2,1,2,Cells,3,Gardnerella_vaginalis;Atopobium_vaginae;Lactobacillus_crispatus 4 | s1-3,1,3,Cells,3,Gardnerella_vaginalis;Atopobium_vaginae;Prevotella_bivia 5 | s1-4,1,4,Cells,3,Atopobium_vaginae;Lactobacillus_crispatus;Streptococcus_agalactiae 6 | s1-5,1,5,Cells,2,Gardnerella_vaginalis;Prevotella_bivia 7 | s1-6,1,6,Cells,3,Atopobium_vaginae;Lactobacillus_iners;Prevotella_bivia 8 | s1-7,1,7,Cells,2,Atopobium_vaginae;Streptococcus_agalactiae 9 | s1-8,1,8,Cells,2,Gardnerella_vaginalis;Streptococcus_agalactiae 10 | s1-9,1,9,Cells,3,Atopobium_vaginae;Sneathia_amnii;Streptococcus_agalactiae 11 | s1-10,1,10,Cells,3,Atopobium_vaginae;Lactobacillus_crispatus;Sneathia_amnii 12 | s1-11,1,11,Cells,3,Gardnerella_vaginalis;Lactobacillus_crispatus;Lactobacillus_iners 13 | s1-12,1,12,Cells,2,Atopobium_vaginae;Prevotella_bivia 14 | s1-13,1,13,Cells,3,Lactobacillus_crispatus;Prevotella_bivia;Sneathia_amnii 15 | s1-14,1,14,Cells,2,Lactobacillus_crispatus;Streptococcus_agalactiae 16 | s1-15,1,15,Cells,3,Atopobium_vaginae;Lactobacillus_iners;Streptococcus_agalactiae 17 | s1-16,1,16,Cells,2,Lactobacillus_iners;Sneathia_amnii 18 | s1-17,1,17,Cells,1,Streptococcus_agalactiae 19 | s1-18,1,18,Cells,2,Gardnerella_vaginalis;Lactobacillus_crispatus 20 | s1-19,1,19,Cells,3,Lactobacillus_iners;Prevotella_bivia;Streptococcus_agalactiae 21 | s1-20,1,20,Cells,2,Prevotella_bivia;Streptococcus_agalactiae 22 | s1-21,1,21,Cells,3,Atopobium_vaginae;Prevotella_bivia;Streptococcus_agalactiae 23 | s1-22,1,22,Cells,3,Atopobium_vaginae;Lactobacillus_iners;Sneathia_amnii 24 | s1-23,1,23,Cells,7,Gardnerella_vaginalis;Atopobium_vaginae;Lactobacillus_crispatus;Lactobacillus_iners;Prevotella_bivia;Sneathia_amnii;Streptococcus_agalactiae 25 | s1-24,1,24,Cells,3,Gardnerella_vaginalis;Sneathia_amnii;Streptococcus_agalactiae 26 | s1-25,1,25,Cells,3,Gardnerella_vaginalis;Lactobacillus_iners;Streptococcus_agalactiae 27 | s1-26,1,26,Cells,3,Gardnerella_vaginalis;Prevotella_bivia;Streptococcus_agalactiae 28 | s1-27,1,27,Cells,3,Gardnerella_vaginalis;Lactobacillus_crispatus;Prevotella_bivia 29 | s1-28,1,28,Cells,1,Lactobacillus_crispatus 30 | s1-29,1,29,Cells,2,Gardnerella_vaginalis;Sneathia_amnii 31 | s1-30,1,30,Cells,3,Gardnerella_vaginalis;Lactobacillus_crispatus;Sneathia_amnii 32 | s1-31,1,31,Cells,2,Lactobacillus_iners;Prevotella_bivia 33 | s1-32,1,32,Cells,2,Atopobium_vaginae;Lactobacillus_crispatus 34 | s1-33,1,33,Cells,2,Lactobacillus_crispatus;Lactobacillus_iners 35 | s1-34,1,34,Cells,1,Atopobium_vaginae 36 | s1-35,1,35,Cells,4,Gardnerella_vaginalis;Lactobacillus_iners;Prevotella_bivia;Sneathia_amnii 37 | s1-36,1,36,Cells,3,Lactobacillus_iners;Sneathia_amnii;Streptococcus_agalactiae 38 | s1-37,1,37,Cells,3,Gardnerella_vaginalis;Atopobium_vaginae;Streptococcus_agalactiae 39 | s1-38,1,38,Cells,2,Prevotella_bivia;Sneathia_amnii 40 | s1-39,1,39,Cells,2,Gardnerella_vaginalis;Lactobacillus_iners 41 | s1-40,1,40,Cells,2,Lactobacillus_crispatus;Sneathia_amnii 42 | s2-1,2,1,Cells,1,Streptococcus_agalactiae 43 | s2-2,2,2,Cells,3,Lactobacillus_crispatus;Sneathia_amnii;Streptococcus_agalactiae 44 | s2-3,2,3,Cells,3,Gardnerella_vaginalis;Sneathia_amnii;Streptococcus_agalactiae 45 | s2-4,2,4,Cells,2,Atopobium_vaginae;Sneathia_amnii 46 | s2-5,2,5,Cells,2,Atopobium_vaginae;Lactobacillus_iners 47 | s2-6,2,6,Cells,3,Gardnerella_vaginalis;Atopobium_vaginae;Sneathia_amnii 48 | s2-7,2,7,Cells,3,Lactobacillus_iners;Prevotella_bivia;Streptococcus_agalactiae 49 | s2-8,2,8,Cells,3,Gardnerella_vaginalis;Lactobacillus_iners;Prevotella_bivia 50 | s2-9,2,9,Cells,3,Gardnerella_vaginalis;Lactobacillus_crispatus;Prevotella_bivia 51 | s2-10,2,10,Cells,1,Sneathia_amnii 52 | s2-11,2,11,Cells,3,Gardnerella_vaginalis;Lactobacillus_crispatus;Streptococcus_agalactiae 53 | s2-12,2,12,Cells,3,Gardnerella_vaginalis;Atopobium_vaginae;Streptococcus_agalactiae 54 | s2-13,2,13,Cells,3,Atopobium_vaginae;Lactobacillus_crispatus;Prevotella_bivia 55 | s2-14,2,14,Cells,7,Gardnerella_vaginalis;Atopobium_vaginae;Lactobacillus_crispatus;Lactobacillus_iners;Prevotella_bivia;Sneathia_amnii;Streptococcus_agalactiae 56 | s2-15,2,15,Cells,3,Prevotella_bivia;Sneathia_amnii;Streptococcus_agalactiae 57 | s2-16,2,16,Cells,3,Lactobacillus_crispatus;Lactobacillus_iners;Streptococcus_agalactiae 58 | s2-17,2,17,Cells,3,Gardnerella_vaginalis;Atopobium_vaginae;Lactobacillus_iners 59 | s2-18,2,18,Cells,1,Atopobium_vaginae 60 | s2-19,2,19,Cells,2,Lactobacillus_crispatus;Lactobacillus_iners 61 | s2-20,2,20,Cells,3,Gardnerella_vaginalis;Atopobium_vaginae;Lactobacillus_crispatus 62 | s2-21,2,21,Cells,2,Lactobacillus_crispatus;Streptococcus_agalactiae 63 | s2-22,2,22,Cells,1,Prevotella_bivia 64 | s2-23,2,23,Cells,2,Atopobium_vaginae;Prevotella_bivia 65 | s2-24,2,24,Cells,1,Lactobacillus_iners 66 | s2-25,2,25,Cells,3,Lactobacillus_iners;Sneathia_amnii;Streptococcus_agalactiae 67 | s2-26,2,26,Cells,3,Lactobacillus_crispatus;Lactobacillus_iners;Prevotella_bivia 68 | s2-27,2,27,Cells,3,Atopobium_vaginae;Lactobacillus_iners;Streptococcus_agalactiae 69 | s2-28,2,28,Cells,2,Lactobacillus_crispatus;Prevotella_bivia 70 | s2-29,2,29,Cells,2,Lactobacillus_iners;Streptococcus_agalactiae 71 | s2-30,2,30,Cells,2,Lactobacillus_crispatus;Sneathia_amnii 72 | s2-31,2,31,Cells,3,Atopobium_vaginae;Lactobacillus_crispatus;Sneathia_amnii 73 | s2-32,2,32,Cells,3,Lactobacillus_iners;Prevotella_bivia;Sneathia_amnii 74 | s2-33,2,33,Cells,2,Sneathia_amnii;Streptococcus_agalactiae 75 | s2-34,2,34,Cells,3,Atopobium_vaginae;Prevotella_bivia;Sneathia_amnii 76 | s2-35,2,35,Cells,3,Atopobium_vaginae;Lactobacillus_crispatus;Lactobacillus_iners 77 | s2-36,2,36,Cells,3,Gardnerella_vaginalis;Prevotella_bivia;Sneathia_amnii 78 | s2-37,2,37,Cells,1,Gardnerella_vaginalis 79 | s2-38,2,38,Cells,3,Gardnerella_vaginalis;Lactobacillus_iners;Sneathia_amnii 80 | s2-39,2,39,Cells,2,Gardnerella_vaginalis;Atopobium_vaginae 81 | s2-40,2,40,Cells,3,Lactobacillus_crispatus;Lactobacillus_iners;Sneathia_amnii 82 | -------------------------------------------------------------------------------- /man/anorm.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{anorm} 4 | \alias{anorm} 5 | \title{Aitchison norm of x} 6 | \usage{ 7 | anorm(x, na.rm = FALSE) 8 | } 9 | \arguments{ 10 | \item{na.rm}{Whether to remove NAs and NaNs before calculating.} 11 | } 12 | \description{ 13 | Aitchison norm of x 14 | } 15 | -------------------------------------------------------------------------------- /man/as_matrix.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utilities.R 3 | \name{as_matrix} 4 | \alias{as_matrix} 5 | \title{Coerce a (wide) data frame to a matrix} 6 | \usage{ 7 | as_matrix(.data, rownames = NULL) 8 | } 9 | \description{ 10 | Coerce a (wide) data frame to a matrix 11 | } 12 | -------------------------------------------------------------------------------- /man/bootrep_center.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/compositional-mean.R 3 | \name{bootrep_center} 4 | \alias{bootrep_center} 5 | \title{Generate bootstrap replicates of the sample center} 6 | \usage{ 7 | bootrep_center( 8 | .data, 9 | R = 4000, 10 | N = nrow(.data), 11 | method = "proj", 12 | dist = "dirichlet", 13 | in_scale = "linear", 14 | out_scale = "linear", 15 | denom = NULL, 16 | enframe = FALSE 17 | ) 18 | } 19 | \arguments{ 20 | \item{.data}{All-numeric data frame or matrix with taxa as columns.} 21 | 22 | \item{R}{Number of bootstrap replicates.} 23 | 24 | \item{N}{Number of trials for multinomial resampling.} 25 | 26 | \item{method}{Method for computing the center: "proj", "gm", or "rss".} 27 | 28 | \item{dist}{Distribution for drawing the bootstrap weights: "dirichlet" or 29 | "multinomial".} 30 | 31 | \item{in_scale}{"linear" (default) or "log".} 32 | 33 | \item{out_scale}{"linear" (default) or "log".} 34 | 35 | \item{denom}{Taxa to use in the denominator; if NULL, use all taxa.} 36 | 37 | \item{enframe}{Whether to "enframe" the bootstrap estimates in a tibble.} 38 | } 39 | \description{ 40 | Generate bootstrap replicates of the sample center 41 | } 42 | -------------------------------------------------------------------------------- /man/build_matrix.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utilities.R 3 | \name{build_matrix} 4 | \alias{build_matrix} 5 | \title{Create a matrix from columns of a tidy data frame} 6 | \usage{ 7 | build_matrix(.data, rows, cols, elts, fill = NULL) 8 | } 9 | \arguments{ 10 | \item{.data}{A data frame with columns \code{rows}, \code{cols}, and \code{elts}.} 11 | 12 | \item{rows}{Column that will become the rownames of the matrix.} 13 | 14 | \item{cols}{Column that will become the colnames of the matrix.} 15 | 16 | \item{elts}{Column that will become the matrix elements.} 17 | 18 | \item{fill}{Value to use for missing elements.} 19 | } 20 | \description{ 21 | Note: Setting \code{fill} will replace NAs and NaNs, along with elements 22 | corresponding to missing rows, with the value of \code{fill}. 23 | } 24 | -------------------------------------------------------------------------------- /man/calibrate.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calibrate.R 3 | \name{calibrate} 4 | \alias{calibrate} 5 | \alias{calibrate.matrix} 6 | \alias{calibrate.otu_table} 7 | \alias{calibrate.phyloseq} 8 | \title{Calibrate a relative-abundance matrix by a bias vector} 9 | \usage{ 10 | calibrate(observed, bias, ...) 11 | 12 | \method{calibrate}{matrix}(observed, bias, margin, norm = "close") 13 | 14 | \method{calibrate}{otu_table}(observed, bias, norm = "close") 15 | 16 | \method{calibrate}{phyloseq}(observed, bias, norm = "close", mean_name = ".mean_efficiency") 17 | } 18 | \arguments{ 19 | \item{observed}{An abundance matrix or phyloseq object containing one} 20 | 21 | \item{bias}{A numeric vector of relative efficiencies or an object of class 22 | 'mc_bias_fit' (from which efficiencies will be extracted)} 23 | 24 | \item{margin}{Matrix margin that corresponds to observations (samples); 25 | \code{1} for rows, \code{2} for columns} 26 | 27 | \item{norm}{String specifying how to normalize the calibrated observations; 28 | see Details.} 29 | 30 | \item{mean_name}{Character vector or NULL. Name of the column in the sample 31 | data in which to store the mean efficiency, or NULL to skip.} 32 | } 33 | \description{ 34 | Calibration via the simple deterministic procedure described in McLaren, 35 | Willis, and Callahan (2019), simply involved dividing the observed vector of 36 | relative abundances by the estimated bias vector and (optionally) 37 | normalizing the result to sum to 1 or some other chosen value. 38 | } 39 | \details{ 40 | Normalization options specified by \code{norm}: 41 | \itemize{ 42 | \item "close": Divide the calibrated abundance vector by its sum, so that it 43 | sums to 1 44 | \item "keep": Keep the same total abundance as the original observation 45 | \item "none": Return the calibrated abundances without any normalization 46 | } 47 | 48 | If \code{bias} is named, then the names must agree with the taxa names in 49 | \code{observed} and will be used to reorder \code{bias} to match the taxa order in 50 | \code{observed}. 51 | } 52 | \seealso{ 53 | \code{\link[=perturb]{perturb()}} \code{\link[=estimate_bias]{estimate_bias()}} 54 | } 55 | -------------------------------------------------------------------------------- /man/center.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/compositional-mean.R 3 | \name{center} 4 | \alias{center} 5 | \title{Compute the center (compositional mean) of a set of compositions} 6 | \usage{ 7 | center( 8 | .data, 9 | weights = rep(1, nrow(.data)), 10 | method = "proj", 11 | in_scale = "linear", 12 | out_scale = "linear", 13 | denom = NULL, 14 | enframe = FALSE, 15 | components = FALSE 16 | ) 17 | } 18 | \arguments{ 19 | \item{.data}{All-numeric data frame or matrix with taxa as columns.} 20 | 21 | \item{weights}{Sample (row) weights.} 22 | 23 | \item{method}{Method for computing the center: "proj", "gm", or "rss".} 24 | 25 | \item{in_scale}{"linear" or "log".} 26 | 27 | \item{out_scale}{"linear" or "log".} 28 | 29 | \item{denom}{Taxa to use in the denominator; if NULL, use all taxa.} 30 | 31 | \item{enframe}{Whether to return the bias estimate as a two-column tibble.} 32 | } 33 | \description{ 34 | Unobserved values should be marked as NaN. 35 | } 36 | -------------------------------------------------------------------------------- /man/center_elts.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{center_elts} 4 | \alias{center_elts} 5 | \title{Geometrically center the elements of x} 6 | \usage{ 7 | center_elts(x, na.rm = FALSE) 8 | } 9 | \description{ 10 | Geometrically center the elements of x 11 | } 12 | -------------------------------------------------------------------------------- /man/close_elts.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{close_elts} 4 | \alias{close_elts} 5 | \title{Close the elements of x to proportions} 6 | \usage{ 7 | close_elts(x, na.rm = FALSE) 8 | } 9 | \description{ 10 | Close the elements of x to proportions 11 | } 12 | -------------------------------------------------------------------------------- /man/clr.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{clr} 4 | \alias{clr} 5 | \title{Compute the centered log-ratio transform of x} 6 | \usage{ 7 | clr(x, base = exp(1), na.rm = FALSE) 8 | } 9 | \arguments{ 10 | \item{x}{Vector of abundances.} 11 | 12 | \item{base}{Base for logarithm} 13 | } 14 | \description{ 15 | Compute the centered log-ratio transform of x 16 | } 17 | -------------------------------------------------------------------------------- /man/compute_ratios.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ratios.R 3 | \name{compute_ratios} 4 | \alias{compute_ratios} 5 | \title{Compute taxon ratios from a tidy data frame} 6 | \usage{ 7 | compute_ratios( 8 | .data, 9 | group_vars = c("Sample"), 10 | comp_vars = setdiff(names(dplyr::select_if(.data, is.numeric)), group_vars), 11 | drop = TRUE 12 | ) 13 | } 14 | \arguments{ 15 | \item{drop}{Whether to drop the individual taxon quantities} 16 | } 17 | \description{ 18 | Assumes the taxon variable name is \code{Taxon} 19 | } 20 | -------------------------------------------------------------------------------- /man/cooccurrence.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bias-helpers.R 3 | \name{cooccurrence} 4 | \alias{cooccurrence} 5 | \alias{cooccurrence_matrix} 6 | \alias{cooccurrence_network} 7 | \alias{cooccurrence_components} 8 | \title{Taxon co-occurrence network} 9 | \usage{ 10 | cooccurrence_matrix(mat, all = TRUE) 11 | 12 | cooccurrence_network(mat, all = TRUE) 13 | 14 | cooccurrence_components(mat, all = TRUE, enframe = FALSE) 15 | } 16 | \arguments{ 17 | \item{mat}{A compositional error matrix} 18 | 19 | \item{all}{Whether to include taxa that aren't in any multi-taxon samples} 20 | 21 | \item{enframe}{Whether to "enframe" the returned vector} 22 | } 23 | \description{ 24 | Functions for probing the taxon co-occurrence network, used for checking if 25 | the bias estimated by the \code{center()} function is fully-determined. 26 | } 27 | \details{ 28 | The edges are weighted by the number of samples the pair of taxa co-occur in 29 | and so provide some information about the precision of the pairwise bias 30 | estimate. 31 | } 32 | \section{Functions}{ 33 | \itemize{ 34 | \item \code{cooccurrence_matrix}: Adjacency matrix of the co-occurrence network 35 | 36 | \item \code{cooccurrence_network}: Co-occurrence network as an \code{igraph} object 37 | 38 | \item \code{cooccurrence_components}: Connected components of the co-occurrence network 39 | }} 40 | 41 | -------------------------------------------------------------------------------- /man/corner.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utilities.R 3 | \docType{import} 4 | \name{corner} 5 | \alias{corner} 6 | \title{Objects exported from other packages} 7 | \keyword{internal} 8 | \description{ 9 | These objects are imported from other packages. Follow the links 10 | below to see their documentation. 11 | 12 | \describe{ 13 | \item{useful}{\code{\link[useful]{corner}}} 14 | }} 15 | 16 | -------------------------------------------------------------------------------- /man/estimate_bias.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/estimate.R 3 | \name{estimate_bias} 4 | \alias{estimate_bias} 5 | \alias{estimate_bias.matrix} 6 | \alias{estimate_bias.otu_table} 7 | \alias{estimate_bias.phyloseq} 8 | \title{Estimate bias from control measurements} 9 | \usage{ 10 | estimate_bias(observed, actual, ...) 11 | 12 | \method{estimate_bias}{matrix}(observed, actual, margin, boot = FALSE, times = 1000) 13 | 14 | \method{estimate_bias}{otu_table}(observed, actual, ...) 15 | 16 | \method{estimate_bias}{phyloseq}(observed, actual, ...) 17 | } 18 | \arguments{ 19 | \item{observed}{Abundance matrix of observed compositions.} 20 | 21 | \item{actual}{Abundance matrix of actual or reference compositions for the 22 | same samples and taxa in \code{observed}.} 23 | 24 | \item{...}{Arguments passed to the matrix method.} 25 | 26 | \item{margin}{Matrix margin that corresponds to observations (samples); 27 | \code{1} for rows, \code{2} for columns.} 28 | 29 | \item{boot}{Whether to perform bootstrapping.} 30 | 31 | \item{times}{Number of bootstrap replicates.} 32 | } 33 | \value{ 34 | A \code{mc_bias_fit} object with \code{\link[=coef]{coef()}}, \code{\link[=fitted]{fitted()}}, \code{\link[=residuals]{residuals()}}, and 35 | \code{\link[=summary]{summary()}} methods. 36 | } 37 | \description{ 38 | Estimate bias using the compositional least-squares approach described in 39 | McLaren, Willis, and Callahan (2019). 40 | } 41 | \details{ 42 | Bias is estimated by applying \code{\link[=center]{center()}} to the compositional error matrix 43 | defined by \code{observed/actual}, which requires that \code{observed} and \code{actual} 44 | are non-zero for the same sample-taxa pairs. For convenience, this 45 | function will automatically set values in \code{observed} to 0 whose 46 | corresponding entries are 0 in \code{actual}, but it is up to you to replace 0 47 | values in \code{observed} with a non-zero value (such as a pseudocount). 48 | 49 | Requirements for \code{observed} and \code{actual}: The row and column names (for 50 | matrices) or taxa and sample names (for phyloseq objects) must match, but 51 | can be in different orders. Any taxa and samples in \code{observed} but not in 52 | \code{actual} will be dropped prior to estimation. 53 | } 54 | \examples{ 55 | # Load data from the cellular mock communities of Brooks et al 2015 56 | dr <- system.file("extdata", package = "metacal") 57 | list.files(dr) 58 | actual <- file.path(dr, "brooks2015-actual.csv") |> 59 | read.csv(row.names = "Sample") |> 60 | as("matrix") 61 | observed <- file.path(dr, "brooks2015-observed.csv") |> 62 | read.csv(row.names = "Sample") |> 63 | subset(select = - Other) |> 64 | as("matrix") 65 | sam <- file.path(dr, "brooks2015-sample-data.csv") |> read.csv() 66 | 67 | # Estimate bias with bootstrapping for error estimation 68 | mc_fit <- estimate_bias(observed, actual, margin = 1, boot = TRUE) 69 | summary(mc_fit) 70 | } 71 | \seealso{ 72 | \code{\link[=center]{center()}} \code{\link[=calibrate]{calibrate()}} 73 | } 74 | -------------------------------------------------------------------------------- /man/gm.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{gm} 4 | \alias{gm} 5 | \title{Geometric (multiplicative) version of the function f} 6 | \usage{ 7 | gm(f) 8 | } 9 | \description{ 10 | Geometric (multiplicative) version of the function f 11 | } 12 | -------------------------------------------------------------------------------- /man/gm_abs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{gm_abs} 4 | \alias{gm_abs} 5 | \title{Geometric absolute value of x} 6 | \usage{ 7 | gm_abs(x) 8 | } 9 | \description{ 10 | Geometric absolute value of x 11 | } 12 | -------------------------------------------------------------------------------- /man/gm_mean.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{gm_mean} 4 | \alias{gm_mean} 5 | \title{Geometric mean of x} 6 | \usage{ 7 | gm_mean(x, na.rm = FALSE) 8 | } 9 | \description{ 10 | Geometric mean of x 11 | } 12 | -------------------------------------------------------------------------------- /man/gm_range.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{gm_range} 4 | \alias{gm_range} 5 | \title{Geometric range of x} 6 | \usage{ 7 | gm_range(x) 8 | } 9 | \description{ 10 | Geometric range of x 11 | } 12 | -------------------------------------------------------------------------------- /man/gm_sd.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{gm_sd} 4 | \alias{gm_sd} 5 | \title{Geometric standard deviation of x} 6 | \usage{ 7 | gm_sd(x, na.rm = FALSE) 8 | } 9 | \description{ 10 | Note, uses denominator n-1 11 | } 12 | -------------------------------------------------------------------------------- /man/import_phyloseq.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metacal.R 3 | \name{import_phyloseq} 4 | \alias{import_phyloseq} 5 | \title{Import phyloseq classes and functions} 6 | \description{ 7 | Import phyloseq classes and functions 8 | } 9 | -------------------------------------------------------------------------------- /man/log_center_proj.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/compositional-mean.R 3 | \name{log_center_proj} 4 | \alias{log_center_proj} 5 | \title{Compute the log center by the projection method} 6 | \usage{ 7 | log_center_proj(mat, weights = rep(1, nrow(mat))) 8 | } 9 | \description{ 10 | Compute the log center by the projection method, which allows for missing 11 | observations. 12 | } 13 | \references{ 14 | van den Boogaart KG, Tolosana-Delgado R, Bren M. 2006. Concepts 15 | for handling of zeros and missing values in compositional data. Proc IAMG 16 | 6:1-4. http://www.stat.boogaart.de/Publications/iamg06_s07_01.pdf 17 | 18 | Bren M, Tolosana-Delgado R, van den Boogaart KG. 2008. News from 19 | "compositions", the R package. 20 | https://core.ac.uk/download/pdf/132548286.pdf 21 | } 22 | -------------------------------------------------------------------------------- /man/log_center_rss.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/compositional-mean.R 3 | \name{log_center_rss} 4 | \alias{log_center_rss} 5 | \title{Compute the log center by numerical optimization} 6 | \usage{ 7 | log_center_rss(mat, weights = rep(1, nrow(mat)), bound = 10) 8 | } 9 | \arguments{ 10 | \item{bound}{Single number giving the lower and upper bound on the alr 11 | efficiencies ("rss" only).} 12 | } 13 | \description{ 14 | Compute the log center by numerical optimization 15 | } 16 | -------------------------------------------------------------------------------- /man/logit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{logit} 4 | \alias{logit} 5 | \title{Logit (log-odds) of the probability vector x} 6 | \usage{ 7 | logit(x) 8 | } 9 | \description{ 10 | Logit (log-odds) of the probability vector x 11 | } 12 | -------------------------------------------------------------------------------- /man/mean_efficiency.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mean_efficiency.R 3 | \name{mean_efficiency} 4 | \alias{mean_efficiency} 5 | \alias{mean_efficiency.matrix} 6 | \alias{mean_efficiency.otu_table} 7 | \alias{mean_efficiency.phyloseq} 8 | \alias{mean_efficiency.mc_bias_fit} 9 | \title{Compute sample mean efficiencies} 10 | \usage{ 11 | mean_efficiency(x, ...) 12 | 13 | \method{mean_efficiency}{matrix}(x, bias, margin, type) 14 | 15 | \method{mean_efficiency}{otu_table}(x, bias, type) 16 | 17 | \method{mean_efficiency}{phyloseq}(x, bias, type) 18 | 19 | \method{mean_efficiency}{mc_bias_fit}(x, newdata = NULL, margin = NULL, type = NULL) 20 | } 21 | \arguments{ 22 | \item{x}{A matrix, a phyloseq object with an otu_table, or an object of 23 | class 'mc_bias_fit'} 24 | 25 | \item{bias}{A (possibly named) numeric vector of relative efficiencies} 26 | 27 | \item{margin}{The margin containing the samples (observations)} 28 | 29 | \item{type}{'actual' or 'observed', indicating the type of abundance 30 | profiles in the matrix \code{x} or \code{newdata}} 31 | 32 | \item{newdata}{NULL or an abundance matrix} 33 | } 34 | \description{ 35 | Given a matrix of 'observed' or 'actual' (e.g. calibrated) abundance 36 | profiles and a vector of relative efficiencies, compute the estimated mean 37 | efficiency for each sample. 38 | } 39 | \details{ 40 | The mean efficiency of a sample equals \code{weighted.mean(bias, y)}, where 41 | \code{bias} is the vector of taxa efficiencies and \code{y} is the vector of taxa 42 | proportions. 43 | 44 | The \code{type \%in\% c('actual', 'observed')} specifies whether the data is 45 | 'actual' (i.e. nominally known or calibrated abundances) or 'observed' (i.e. 46 | uncalibrated) data. 'Observed' data is calibrated to determine \code{y} prior to 47 | computing the mean efficiency. 48 | 49 | If \code{x} is an \code{mc_bias_fit} object, then the efficiencies will be extracted 50 | with \code{coef(x)}. An abundance matrix can optionally be given with \code{newdata}; 51 | otherwise, the mean efficiency will be computed for the control samples in 52 | \code{x}. 53 | 54 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} 55 | } 56 | \seealso{ 57 | \code{\link[=estimate_bias]{estimate_bias()}} 58 | } 59 | -------------------------------------------------------------------------------- /man/metacal-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metacal-package.R 3 | \docType{package} 4 | \name{metacal-package} 5 | \alias{metacal} 6 | \alias{metacal-package} 7 | \title{metacal: Bias estimation and calibration for metagenomics experiments} 8 | \description{ 9 | The metacal package provides tools for bias estimation and calibration in marker-gene and metagenomics sequencing experiments, using the methods developed in https://elifesciences.org/articles/46923. 10 | } 11 | \seealso{ 12 | Useful links: 13 | \itemize{ 14 | \item \url{https://mikemc.github.io/metacal} 15 | \item \url{https://github.com/mikemc/metacal} 16 | \item Report bugs at \url{https://github.com/mikemc/metacal/issues} 17 | } 18 | 19 | } 20 | \author{ 21 | \strong{Maintainer}: Michael McLaren \email{m.mclaren42@gmail.com} (\href{https://orcid.org/0000-0003-1575-473X}{ORCID}) 22 | 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/mutate_by.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utilities.R 3 | \name{mutate_by} 4 | \alias{mutate_by} 5 | \title{Mutate within groups} 6 | \usage{ 7 | mutate_by(.data, group_vars, ...) 8 | } 9 | \description{ 10 | Mutate within groups 11 | } 12 | -------------------------------------------------------------------------------- /man/odds.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{odds} 4 | \alias{odds} 5 | \title{Odds of the probability vector x} 6 | \usage{ 7 | odds(x) 8 | } 9 | \description{ 10 | Odds of the probability vector x 11 | } 12 | -------------------------------------------------------------------------------- /man/pairwise_ratios.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ratios.R 3 | \name{pairwise_ratios} 4 | \alias{pairwise_ratios} 5 | \alias{pairwise_ratios.default} 6 | \alias{pairwise_ratios.matrix} 7 | \alias{pairwise_ratios.otu_table} 8 | \alias{pairwise_ratios.phyloseq} 9 | \title{Pairwise ratios of vector elements and matrix rows or columns} 10 | \usage{ 11 | pairwise_ratios(x, ..., f = `/`, filter = TRUE, set_names = TRUE, sep = ":") 12 | 13 | \method{pairwise_ratios}{default}(x, f = `/`, filter = TRUE, set_names = TRUE, sep = ":") 14 | 15 | \method{pairwise_ratios}{matrix}(x, margin, f = `/`, filter = TRUE, set_names = TRUE, sep = ":") 16 | 17 | \method{pairwise_ratios}{otu_table}(x, margin = "taxa", f = `/`, filter = TRUE, sep = ":") 18 | 19 | \method{pairwise_ratios}{phyloseq}(x, margin = "taxa", f = `/`, filter = TRUE, sep = ":") 20 | } 21 | \arguments{ 22 | \item{x}{A vector or matrix} 23 | 24 | \item{f}{Vectorized binary function applied to numerator and denominator} 25 | 26 | \item{filter}{Whether to filter out redundant pairs} 27 | 28 | \item{set_names}{Whether to set names for the pairs} 29 | 30 | \item{sep}{Seperator for pair names} 31 | 32 | \item{margin}{Margin (1 = rows, 2 = cols) of matrix x to compute ratios of} 33 | } 34 | \description{ 35 | For a matrix, computes the ratios of the supplied margin (1 = rows, 2 = 36 | cols). Otherwise, computes the ratios of the elements. 37 | } 38 | \examples{ 39 | mat <- seq(10) |> 40 | matrix(nrow = 2) 41 | rownames(mat) <- paste0('r', seq(2)) 42 | colnames(mat) <- paste0('c', seq(5)) 43 | 44 | pairwise_ratios(mat, 2) 45 | pairwise_ratios(mat[1,]) 46 | } 47 | -------------------------------------------------------------------------------- /man/perturb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calibrate.R 3 | \name{perturb} 4 | \alias{perturb} 5 | \alias{perturb.matrix} 6 | \alias{perturb.otu_table} 7 | \alias{perturb.phyloseq} 8 | \alias{perturb.mc_bias_fit} 9 | \title{Compositionally perturb a relative-abundance matrix} 10 | \usage{ 11 | perturb(x, y, ...) 12 | 13 | \method{perturb}{matrix}(x, y, margin, norm = "close") 14 | 15 | \method{perturb}{otu_table}(x, y, norm = "close") 16 | 17 | \method{perturb}{phyloseq}(x, y, norm = "close") 18 | 19 | \method{perturb}{mc_bias_fit}(x, y) 20 | } 21 | \arguments{ 22 | \item{x}{An abundance matrix or phyloseq object containing one} 23 | 24 | \item{y}{A numeric vector with which to perturb the observations in x} 25 | 26 | \item{margin}{Matrix margin that corresponds to observations (samples); 27 | \code{1} for rows, \code{2} for columns} 28 | 29 | \item{norm}{String specifying how to normalize the perturbed observations; 30 | see Details.} 31 | } 32 | \description{ 33 | The perturbation of two compositional vectors \code{v} and \code{y} is given (up to 34 | compositional equivalence) by the elementwise product \code{v * y}. 35 | } 36 | \details{ 37 | Let \code{w = v * y}, where \code{v} is a row or column of \code{x}. The normalization 38 | options specified by the \code{norm} argument are 39 | \itemize{ 40 | \item "close" Return the compositional closure of w into the simplex, 41 | \code{w / sum(w)} 42 | \item "keep" Keep the same total abundance as the original vector by returning 43 | \code{w * sum(v) / sum(w)} 44 | \item "none" Return \code{w} without any normalization 45 | } 46 | 47 | If \code{y} is named, then the names must agree with the taxa names in \code{x} and 48 | will be used to reorder \code{y} to match the taxa order in \code{x}. 49 | } 50 | \seealso{ 51 | \code{\link[=calibrate]{calibrate()}} 52 | } 53 | -------------------------------------------------------------------------------- /man/proj_mat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/compositional-mean.R 3 | \name{proj_mat} 4 | \alias{proj_mat} 5 | \title{Projection matrix P_M} 6 | \usage{ 7 | proj_mat(K, M = c()) 8 | } 9 | \arguments{ 10 | \item{K}{number of elements (taxa)} 11 | 12 | \item{M}{set of missing elements (default is none missing)} 13 | } 14 | \description{ 15 | Used internally for the "proj" method of computing the compositional mean. 16 | See vandenBoogaart2006 and Bren2008. 17 | } 18 | -------------------------------------------------------------------------------- /man/xydist.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/math.R 3 | \name{xydist} 4 | \alias{xydist} 5 | \title{Distance or dissimilarity between relative abundance vectors x and y} 6 | \usage{ 7 | xydist(x, y, method = "aitchison", trim = FALSE) 8 | } 9 | \arguments{ 10 | \item{method}{Distance/dissimilarity measure.} 11 | 12 | \item{trim}{Should x and y be reduced to their common positive elements 13 | before computing the Aitchison distance (otherwise, the distance will be 14 | Inf). 15 | 16 | method == "aitchison" -> Aitchison distance 17 | method == "bray" -> Bray-Curtis dissimilarity between x and y. Note, 18 | converts x and y to proportions before computing.} 19 | } 20 | \description{ 21 | Distance or dissimilarity between relative abundance vectors x and y 22 | } 23 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(metacal) 3 | 4 | test_check("metacal") 5 | -------------------------------------------------------------------------------- /tests/testthat/test-calibrate.R: -------------------------------------------------------------------------------- 1 | # run just this file: 2 | # devtools::test_active_file(here::here("tests", "testthat", "test-calibrate.R")) 3 | # 4 | # Covers estimate_bias(), perturb(), calibrate() 5 | 6 | # Setup ----------------------------------------------------------------------- 7 | 8 | test_xy <- function(n_taxa, n_samples) { 9 | set.seed(42) 10 | # random abundance matrix with zeros 11 | x <- sample(0:5, n_taxa*n_samples, replace = TRUE) %>% 12 | matrix(nrow = n_taxa) 13 | rownames(x) <- paste0("t", seq(n_taxa)) 14 | colnames(x) <- paste0("s", seq(n_samples)) 15 | # perturbation vector 16 | y <- seq(n_taxa) 17 | 18 | list(x = x, y = y) 19 | } 20 | 21 | l <- test_xy(5, 10) 22 | x <- l$x; y <- l$y 23 | otu <- otu_table(x, taxa_are_rows = TRUE) 24 | 25 | # Tests ----------------------------------------------------------------------- 26 | 27 | test_that("`estimate_bias()` correctly recovers a deterministic perturbation", { 28 | actual <- otu 29 | bias <- rlang::set_names(center_elts(y), phyloseq::taxa_names(otu)) 30 | observed <- perturb(otu, bias, norm = "keep") 31 | # Mix up the sample and taxa order 32 | observed <- observed[rownames(observed) %>% rev, colnames(observed) %>% rev] 33 | 34 | expect_equal(bias, estimate_bias(observed, actual) %>% coef) 35 | expect_equal(bias, estimate_bias(observed, actual %>% t) %>% coef) 36 | 37 | # non-zero values is observed that are zero in actual should be automatically 38 | # zeroed with a message 39 | observed1 <- otu_table(observed + 23 * (observed == 0), taxa_are_rows = TRUE) 40 | expect_message(fit <- estimate_bias(observed1, actual, boot = TRUE, times = 2)) 41 | expect_equal(bias, coef(fit)) 42 | 43 | # Matrices stored in `fit` should have samples as rows, and so work without 44 | # error in perturb() with `margin = 1`. 45 | perturb(fit$actual, fit$estimate, margin = 1, norm = "close") 46 | 47 | # Check perturb on mc_bias_fit's 48 | x <- perturb(fit, 1/fit$estimate) 49 | expect_equal(x$estimate / x$estimate, apply(x$bootreps, 2, mean)) 50 | expect_error(perturb(fit, 1:3)) 51 | 52 | # NOTE: doesn't quite fit this test title 53 | # Test that calibrate works on mc_bias_fit objects 54 | # fit <- estimate_bias(observed, actual) 55 | expect_equal( 56 | calibrate(observed, fit), 57 | calibrate(observed, coef(fit)) 58 | ) 59 | 60 | # Test mean efficiency computation 61 | me1 <- apply(fit$actual, 1, function(x) weighted.mean(coef(fit), x)) 62 | me2 <- mean_efficiency(fit$actual, coef(fit), margin = 1, type = 'actual') 63 | me3 <- mean_efficiency(fit) 64 | expect_equal(me1, me3) 65 | expect_equal(me2, me3) 66 | me4 <- actual %>% 67 | phyloseq::transform_sample_counts(close_elts) %>% 68 | perturb(coef(fit), norm = 'none') %>% 69 | phyloseq::sample_sums() %>% 70 | .[names(me1)] 71 | expect_equal(me1, me4) 72 | 73 | # can also compute within `calibrate()` 74 | sam <- data.frame( 75 | dummy_var = seq(phyloseq::nsamples(observed)), 76 | row.names = sample_names(observed) 77 | ) %>% 78 | phyloseq::sample_data() 79 | cal <- phyloseq::phyloseq(observed, sam) %>% 80 | calibrate(coef(fit), mean_name = 'silly_name') 81 | me5 <- sample_data(cal)$silly_name 82 | names(me5) <- sample_names(cal) 83 | me5 <- me5[names(me1)] 84 | expect_equal(me1, me4) 85 | }) 86 | 87 | test_that("`estimate_bias()` silently drops taxa and samples not in 'actual'", { 88 | actual <- otu %>% 89 | phyloseq::prune_taxa(taxa_names(.)[-3], .) %>% 90 | phyloseq::prune_samples(sample_names(.)[-4], .) 91 | bias <- rlang::set_names(center_elts(y), phyloseq::taxa_names(otu)) 92 | observed <- perturb(otu, bias, norm = "keep") 93 | # Mix up the sample and taxa order 94 | observed <- observed[rownames(observed) %>% rev, colnames(observed) %>% rev] 95 | 96 | expect_equal( 97 | bias[-3] %>% center_elts, 98 | estimate_bias(observed, actual) %>% coef 99 | ) 100 | }) 101 | 102 | test_that("`calibrate()` and `perturb()` are inverse operations", { 103 | expect_equal( 104 | otu, 105 | otu %>% perturb(y, norm = "none") %>% calibrate(y, norm = "none") 106 | ) 107 | mat <- otu %>% as("matrix") 108 | expect_equal( 109 | mat, 110 | mat %>% perturb(y, 2, norm = "none") %>% calibrate(y, 2, norm = "none") 111 | ) 112 | # Should also work if y is named and has a different order 113 | y1 <- rlang::set_names(y, taxa_names(otu)) %>% rev 114 | expect_equal( 115 | otu, 116 | otu %>% perturb(y1, norm = "none") %>% calibrate(y, norm = "none") 117 | ) 118 | }) 119 | 120 | test_that("`calibrate()` (and `perturb()`) normalizations work", { 121 | expect_equal( 122 | rlang::set_names(rep(1, phyloseq::nsamples(otu)), phyloseq::sample_names(otu)), 123 | calibrate(otu, y, norm = "close") %>% phyloseq::sample_sums() 124 | ) 125 | expect_equal( 126 | otu %>% sample_sums, 127 | calibrate(otu, y, norm = "keep") %>% phyloseq::sample_sums() 128 | ) 129 | }) 130 | 131 | test_that("taxa disagreements are properly handled", { 132 | y1 <- rlang::set_names(y, phyloseq::taxa_names(otu)) %>% rev 133 | y2 <- rlang::set_names(y, letters[seq_along(y)]) 134 | # calibrate should work as long as some taxa names are shared with `bias` 135 | cal <- calibrate(otu, y1[1:4]) 136 | expect_identical(taxa_names(cal), intersect(taxa_names(otu), names(y1)[1:4])) 137 | expect_error(calibrate(otu, y[1:4])) 138 | expect_error(calibrate(otu, y2)) 139 | expect_error(calibrate(otu, y2[1:4])) 140 | }) 141 | -------------------------------------------------------------------------------- /tests/testthat/test-center.R: -------------------------------------------------------------------------------- 1 | context("Methods for computing compositional means") 2 | 3 | # Setup ----------------------------------------------------------------------- 4 | 5 | library(tibble) 6 | library(tidyr) 7 | library(dplyr) 8 | 9 | set.seed(1) 10 | # Bias for 5 fake taxa: 11 | K <- 5 12 | taxa <- paste0("T", seq(K)) 13 | bias <- tibble(Taxon = taxa, Bias = exp(rnorm(K, 0, 2))) %>% 14 | mutate( 15 | Bias = center_elts(Bias), 16 | ) 17 | # Fake experimental dataset 1 18 | N <- 10 19 | samples <- paste0("S", seq(N)) 20 | exp1 <- crossing(Sample = samples, Taxon = taxa) %>% 21 | left_join(bias, by = "Taxon") 22 | exp1 <- exp1 %>% 23 | mutate( 24 | Actual = rexp(n(), 1), 25 | Noise = exp(rnorm(n(), mean = log(1), sd = 0.5)), 26 | Observed = Actual * Bias * Noise 27 | ) %>% 28 | group_by(Sample) %>% 29 | # mutate_at(vars(Actual, Noise, Observed), center_elts) %>% 30 | ungroup 31 | # Fake experimental dataset 2 32 | exp2 <- exp1 %>% 33 | mutate( 34 | Actual = Actual * purrr::rbernoulli(n(), p = 0.66), 35 | Observed = Actual * Bias * Noise 36 | ) 37 | # Fake experimental dataset 3 38 | exp3 <- exp1 %>% 39 | mutate( 40 | Actual = case_when( 41 | Sample <= "S5" & Taxon <= "T3" ~ Actual, 42 | Sample <= "S5" & Taxon > "T3" ~ 0, 43 | Sample > "S5" & Taxon <= "T3" ~ 0, 44 | Sample > "S5" & Taxon > "T3" ~ Actual, 45 | ), 46 | Observed = Actual * Bias * Noise 47 | ) 48 | # Get compositional errors in matrix form 49 | d1 <- exp1 %>% 50 | transmute(Sample, Taxon, Error = Observed / Actual) %>% 51 | build_matrix(Sample, Taxon, Error) 52 | d2 <- exp2 %>% 53 | transmute(Sample, Taxon, Error = Observed / Actual) %>% 54 | build_matrix(Sample, Taxon, Error) 55 | d3 <- exp3 %>% 56 | transmute(Sample, Taxon, Error = Observed / Actual) %>% 57 | build_matrix(Sample, Taxon, Error) 58 | # Example set of weights 59 | w <- rmultinom(1, N, rep(1, N))[,1] 60 | 61 | # Deterministic datasets 62 | d4 <- exp1 %>% 63 | build_matrix(Sample, Taxon, Bias) 64 | d5 <- exp2 %>% 65 | transmute(Sample, Taxon, Error = Actual * Bias / Actual) %>% 66 | build_matrix(Sample, Taxon, Error) 67 | 68 | # TODO: Dataset w/ covariance in the errors 69 | 70 | # Detach everything to make sure metacal is importing correctly 71 | detach(package:tibble) 72 | detach(package:tidyr) 73 | detach(package:dplyr) 74 | 75 | # Mean ------------------------------------------------------------------------ 76 | 77 | test_that("all methods agree when all samples have all taxa", { 78 | expect_equal(center(d1, method = "proj"), center(d1, method = "gm")) 79 | expect_equal(center(d1, method = "proj"), center(d1, method = "rss"), 80 | tolerance = 1e-5) 81 | }) 82 | 83 | test_that("the 'proj' and 'rss' methods agree when samples have different taxa, but sufficient overlap", { 84 | expect_equal(center(d2, method = "proj"), center(d2, method = "rss"), 85 | tolerance = 1e-5) 86 | }) 87 | 88 | test_that("the 'gm' method returns all NaNs when some taxa-sample observations are missing", { 89 | expect_equal(center(d2, method = "gm"), 90 | rlang::rep_named(colnames(d2), NaN)) 91 | }) 92 | 93 | test_that("the estimate does not depend on first normalizing the `weights`", { 94 | expect_equal( 95 | center(d2, weights = w, method = "rss"), 96 | center(d2, weights = w / sum(w), method = "rss"), 97 | tolerance = 1e-5) 98 | expect_equal( 99 | center(d2, weights = w, method = "proj"), 100 | center(d2, weights = w / sum(w), method = "proj")) 101 | expect_equal( 102 | center(d2, weights = w, method = "gm"), 103 | center(d2, weights = w / sum(w), method = "gm")) 104 | }) 105 | 106 | test_that("sampling rows or using `weights` gives an equal estimate", { 107 | rows <- sample(N, N, replace = TRUE) 108 | w.rows <- table(factor(rows, seq(N))) %>% c 109 | expect_equal( 110 | center(d1[rows,], method = "gm"), 111 | center(d1, weights = w.rows, method = "gm")) 112 | expect_equal( 113 | center(d2[rows,], method = "proj"), 114 | center(d2, weights = w.rows, method = "proj")) 115 | expect_equal( 116 | center(d2[rows,], method = "rss"), 117 | center(d2, weights = w.rows, method = "rss")) 118 | }) 119 | 120 | test_that("the center is correctly computed when sample and taxa names are missing", { 121 | d2.no_names <- d2 122 | rownames(d2.no_names) <- colnames(d2.no_names) <- NULL 123 | c1 <- center(d2) 124 | names(c1) <- NULL 125 | c2 <- center(d2.no_names) 126 | expect_equal(c1, c2) 127 | }) 128 | 129 | # Additional tests to add 130 | # - Check various in scale and out scale combinations 131 | # - Check behavior in the exp3 case (bias not fully defined) 132 | # - Check that the projection method gives the right answer in the 133 | # deterministic missing observations case 134 | 135 | test_that("`bootrep_center()` output format", { 136 | bootreps <- bootrep_center(d2, R = 5, enframe = FALSE) 137 | bootreps.tb <- bootrep_center(d2, R = 5, enframe = TRUE) 138 | expect_identical(colnames(bootreps), colnames(bootreps)) 139 | expect_identical(nrow(bootreps), 5L) 140 | expect_true(is.matrix(bootreps)) 141 | expect_s3_class(bootreps.tb, "tbl_df") 142 | }) 143 | -------------------------------------------------------------------------------- /tests/testthat/test-ratios.R: -------------------------------------------------------------------------------- 1 | # run just this file: 2 | # devtools::test_active_file(here::here("tests", "testthat", "test-ratios.R")) 3 | 4 | data("enterotype", package = "phyloseq") 5 | 6 | # Test for issue #18 fix 7 | test_that("Maintains name with just 1 item on opposing margin; throws error if 1 item on given margin", { 8 | p0 <- enterotype %>% 9 | phyloseq::prune_taxa(taxa_names(.)[3], .) %>% 10 | phyloseq::prune_samples(sample_names(.)[1:5], .) 11 | p1 <- p0 %>% pairwise_ratios("samples") 12 | expect_equal(taxa_names(p1), taxa_names(p0)) 13 | expect_error(p0 %>% pairwise_ratios("taxa")) 14 | 15 | p0 <- enterotype %>% 16 | phyloseq::prune_taxa(taxa_names(.)[3:5], .) %>% 17 | phyloseq::prune_samples(sample_names(.)[5], .) 18 | p1 <- p0 %>% pairwise_ratios("taxa") 19 | expect_equal(sample_names(p1), sample_names(p0)) 20 | expect_error(p0 %>% pairwise_ratios("samples")) 21 | }) 22 | -------------------------------------------------------------------------------- /tests/testthat/test-utilities.R: -------------------------------------------------------------------------------- 1 | # run just this file: 2 | # devtools::test_active_file(here::here("tests", "testthat", "test-utilities.R")) 3 | 4 | # Setup: Load Brooks files 5 | x <- system.file("extdata", "brooks2015-actual.csv", package = "metacal") %>% 6 | readr::read_csv() %>% 7 | dplyr::arrange(Sample) # Not strictly needed since already in this order 8 | sam <- system.file("extdata", "brooks2015-sample-data.csv", package = "metacal") %>% 9 | readr::read_csv() 10 | 11 | test_that("`as_matrix()` and `build_matrix()` work as inverses", { 12 | y <- x %>% 13 | as_matrix(Sample) 14 | z <- x %>% 15 | tidyr::pivot_longer(-Sample) %>% 16 | build_matrix(Sample, name, value) 17 | expect_equal(y, z) 18 | }) 19 | 20 | test_that("`build_matrix()` works on grouped variables", { 21 | y <- x %>% 22 | dplyr::left_join(sam, by = "Sample") %>% 23 | tidyr::pivot_longer(-colnames(sam), names_to = ".otu") 24 | z <- y %>% 25 | dplyr::group_by(Plate, .otu) %>% 26 | dplyr::summarize(across(value, sum), .groups = "drop_last") %>% 27 | build_matrix(Plate, .otu, value) 28 | expect_equal( 29 | rownames(z), 30 | sam$Plate %>% unique %>% as.character %>% sort 31 | ) 32 | expect_equal( 33 | colnames(z), 34 | y$.otu %>% unique %>% sort 35 | ) 36 | }) 37 | --------------------------------------------------------------------------------