| 1 |
# AGGREGATE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Aggregate ==================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @method aggregate CompositionMatrix |
|
| 8 |
aggregate.CompositionMatrix <- function(x, by, FUN, ..., |
|
| 9 |
simplify = TRUE, drop = TRUE) {
|
|
| 10 | 1x |
x <- group(x, by = by, drop_levels = drop, verbose = FALSE) |
| 11 | 1x |
aggregate(x, FUN, ..., simplify = simplify) |
| 12 |
} |
|
| 13 | ||
| 14 |
#' @export |
|
| 15 |
#' @rdname aggregate |
|
| 16 |
#' @aliases aggregate,CompositionMatrix-method |
|
| 17 |
setMethod("aggregate", "CompositionMatrix", aggregate.CompositionMatrix)
|
|
| 18 | ||
| 19 |
#' @export |
|
| 20 |
#' @method aggregate GroupedComposition |
|
| 21 |
aggregate.GroupedComposition <- function(x, FUN, ..., simplify = TRUE) {
|
|
| 22 |
## Grouping |
|
| 23 | 6x |
aggr <- lapply( |
| 24 | 6x |
X = group_rows(x), |
| 25 | 6x |
FUN = function(i, data, fun, ...) fun(data[i, , drop = FALSE], ...), |
| 26 | 6x |
data = x, |
| 27 | 6x |
fun = FUN, |
| 28 |
... |
|
| 29 |
) |
|
| 30 | ||
| 31 | 6x |
has_dim <- vapply( |
| 32 | 6x |
X = aggr, |
| 33 | 6x |
FUN = function(x) !is.null(nrow(x)) && nrow(x) > 1, |
| 34 | 6x |
FUN.VALUE = logical(1) |
| 35 |
) |
|
| 36 | ||
| 37 | ! |
if (any(has_dim) || !simplify) return(aggr) |
| 38 | 6x |
aggr <- do.call(rbind, aggr) |
| 39 | 6x |
rownames(aggr) <- group_levels(x) |
| 40 | 6x |
aggr |
| 41 |
} |
|
| 42 | ||
| 43 |
#' @export |
|
| 44 |
#' @rdname aggregate |
|
| 45 |
#' @aliases aggregate,GroupedComposition-method |
|
| 46 |
setMethod("aggregate", "GroupedComposition", aggregate.GroupedComposition)
|
| 1 |
# MUTATORS |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Not exported |
|
| 6 |
get_transformation <- function(x) {
|
|
| 7 | ! |
if (methods::is(x, "LR")) return("Pairwise Log-Ratio")
|
| 8 | ! |
if (methods::is(x, "CLR")) return("Centered Log-Ratio")
|
| 9 | ! |
if (methods::is(x, "ALR")) return("Additive Log-Ratio")
|
| 10 | 4x |
if (methods::is(x, "ILR")) return("Isometric Log-Ratio")
|
| 11 | ! |
if (methods::is(x, "PLR")) return("Pivot Log-Ratio")
|
| 12 |
} |
|
| 13 | ||
| 14 |
# Predicates =================================================================== |
|
| 15 |
#' @export |
|
| 16 |
#' @rdname CompositionMatrix-class |
|
| 17 |
is_composition <- function(object) {
|
|
| 18 | 4x |
methods::is(object, "CompositionMatrix") |
| 19 |
} |
|
| 20 | ||
| 21 |
#' @export |
|
| 22 |
#' @rdname LogRatio-class |
|
| 23 |
is_logratio <- function(object) {
|
|
| 24 | ! |
methods::is(object, "LogRatio") |
| 25 |
} |
|
| 26 | ||
| 27 |
#' @export |
|
| 28 |
#' @rdname ReferenceGroups-class |
|
| 29 |
is_grouped <- function(object) {
|
|
| 30 | 129x |
methods::is(object, "ReferenceGroups") |
| 31 |
} |
|
| 32 | ||
| 33 |
# Getter ======================================================================= |
|
| 34 |
#' @export |
|
| 35 |
#' @method labels CompositionMatrix |
|
| 36 |
labels.CompositionMatrix <- function(object, ...) {
|
|
| 37 | 5x |
colnames(object) |
| 38 |
} |
|
| 39 | ||
| 40 |
#' @export |
|
| 41 |
#' @rdname labels |
|
| 42 |
#' @aliases labels,CompositionMatrix-method |
|
| 43 |
setMethod("labels", "CompositionMatrix", labels.CompositionMatrix)
|
|
| 44 | ||
| 45 |
#' @export |
|
| 46 |
#' @method labels LogRatio |
|
| 47 |
labels.LogRatio <- function(object, ...) {
|
|
| 48 | 7x |
object@ratio |
| 49 |
} |
|
| 50 | ||
| 51 |
#' @export |
|
| 52 |
#' @rdname labels |
|
| 53 |
#' @aliases labels,LogRatio-method |
|
| 54 |
setMethod("labels", "LogRatio", labels.LogRatio)
|
|
| 55 | ||
| 56 |
# Weights ====================================================================== |
|
| 57 |
#' @export |
|
| 58 |
#' @method weights ALR |
|
| 59 |
weights.ALR <- function(object, ...) {
|
|
| 60 | ! |
w <- object@weights |
| 61 | ! |
w[-1] * w[1] |
| 62 |
} |
|
| 63 | ||
| 64 |
#' @export |
|
| 65 |
#' @rdname weights |
|
| 66 |
#' @aliases weights,ALR-method |
|
| 67 |
setMethod("weights", "ALR", weights.ALR)
|
|
| 68 | ||
| 69 |
#' @export |
|
| 70 |
#' @method weights LR |
|
| 71 |
weights.LR <- function(object, ...) {
|
|
| 72 | 2x |
w <- object@weights |
| 73 | 2x |
w <- utils::combn( |
| 74 | 2x |
x = w, |
| 75 | 2x |
m = 2, |
| 76 | 2x |
FUN = function(x) Reduce(`*`, x), |
| 77 | 2x |
simplify = FALSE |
| 78 |
) |
|
| 79 | 2x |
unlist(w) |
| 80 |
} |
|
| 81 | ||
| 82 |
#' @export |
|
| 83 |
#' @rdname weights |
|
| 84 |
#' @aliases weights,LR-method |
|
| 85 |
setMethod("weights", "LR", weights.LR)
|
|
| 86 | ||
| 87 |
#' @export |
|
| 88 |
#' @method weights LogRatio |
|
| 89 |
weights.LogRatio <- function(object, ...) {
|
|
| 90 | 5x |
object@weights |
| 91 |
} |
|
| 92 | ||
| 93 |
#' @export |
|
| 94 |
#' @rdname weights |
|
| 95 |
#' @aliases weights,LogRatio-method |
|
| 96 |
setMethod("weights", "LogRatio", weights.LogRatio)
|
|
| 97 | ||
| 98 |
# Totals ======================================================================= |
|
| 99 |
#' @export |
|
| 100 |
#' @rdname totals |
|
| 101 |
#' @aliases totals,CompositionMatrix-method |
|
| 102 | 911x |
setMethod("totals", "CompositionMatrix", function(object) object@totals)
|
| 103 | ||
| 104 |
#' @export |
|
| 105 |
#' @rdname totals |
|
| 106 |
#' @aliases totals,LogRatio-method |
|
| 107 | 15x |
setMethod("totals", "LogRatio", function(object) object@totals)
|
| 108 | ||
| 109 |
#' @export |
|
| 110 |
#' @rdname totals |
|
| 111 |
setMethod( |
|
| 112 |
f = "totals<-", |
|
| 113 |
signature = "CompositionMatrix", |
|
| 114 |
definition = function(object, value) {
|
|
| 115 | 3x |
object@totals <- if (is.null(value)) rowSums(object) else as.numeric(value) |
| 116 | 3x |
methods::validObject(object) |
| 117 | 1x |
object |
| 118 |
} |
|
| 119 |
) |
| 1 |
# OPERATORS |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Closure ====================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname closure |
|
| 8 |
#' @aliases closure,numeric-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "closure", |
|
| 11 |
signature = c(x = "numeric"), |
|
| 12 |
definition = function(x, total = 1, na.rm = TRUE) {
|
|
| 13 | 41x |
x * total / sum(x, na.rm = na.rm) |
| 14 |
} |
|
| 15 |
) |
|
| 16 | ||
| 17 |
#' @export |
|
| 18 |
#' @rdname closure |
|
| 19 |
#' @aliases closure,matrix-method |
|
| 20 |
setMethod( |
|
| 21 |
f = "closure", |
|
| 22 |
signature = c(x = "matrix"), |
|
| 23 |
definition = function(x, total = 1, na.rm = TRUE) {
|
|
| 24 | 10x |
x * total / rowSums(x, na.rm = na.rm) |
| 25 |
} |
|
| 26 |
) |
|
| 27 | ||
| 28 |
# Perturbation ================================================================= |
|
| 29 |
#' @export |
|
| 30 |
#' @rdname arithmetic |
|
| 31 |
#' @aliases `%perturbe%`,CompositionMatrix,CompositionMatrix-method |
|
| 32 |
setMethod( |
|
| 33 |
f = "%perturbe%", |
|
| 34 |
signature = c(x = "CompositionMatrix", y = "CompositionMatrix"), |
|
| 35 |
definition = function(x, y) {
|
|
| 36 | 6x |
arkhe::assert_dimensions(y, dim(x)) |
| 37 | ||
| 38 | ! |
if (all(x <= 0)) x <- 1 / x |
| 39 | 1x |
if (all(y <= 0)) y <- 1 / y |
| 40 | ||
| 41 | 6x |
z <- closure(x * y) |
| 42 | 6x |
z <- methods::initialize(x, z) |
| 43 | 6x |
rownames(z) <- rownames(x) |
| 44 | ||
| 45 | 6x |
z |
| 46 |
} |
|
| 47 |
) |
|
| 48 | ||
| 49 |
#' @export |
|
| 50 |
#' @rdname perturbation |
|
| 51 |
#' @aliases perturbation,numeric,numeric-method |
|
| 52 |
setMethod( |
|
| 53 |
f = "perturbation", |
|
| 54 |
signature = c(x = "numeric", y = "numeric"), |
|
| 55 |
definition = function(x, y) {
|
|
| 56 | 1x |
arkhe::assert_length(y, length(x)) |
| 57 | 1x |
closure(x * y) |
| 58 |
} |
|
| 59 |
) |
|
| 60 | ||
| 61 |
#' @export |
|
| 62 |
#' @rdname perturbation |
|
| 63 |
#' @aliases perturbation,CompositionMatrix,numeric-method |
|
| 64 |
setMethod( |
|
| 65 |
f = "perturbation", |
|
| 66 |
signature = c(x = "CompositionMatrix", y = "numeric"), |
|
| 67 |
definition = function(x, y) {
|
|
| 68 | 3x |
y <- matrix(data = y, nrow = nrow(x), ncol = length(y), byrow = TRUE) |
| 69 | 3x |
x %perturbe% as_composition(y) |
| 70 |
} |
|
| 71 |
) |
|
| 72 | ||
| 73 |
#' @export |
|
| 74 |
#' @rdname perturbation |
|
| 75 |
#' @aliases perturbation,CompositionMatrix,CompositionMatrix-method |
|
| 76 |
setMethod( |
|
| 77 |
f = "perturbation", |
|
| 78 |
signature = c(x = "CompositionMatrix", y = "matrix"), |
|
| 79 |
definition = function(x, y) {
|
|
| 80 | 1x |
x %perturbe% as_composition(y) |
| 81 |
} |
|
| 82 |
) |
|
| 83 | ||
| 84 |
# Powering ===================================================================== |
|
| 85 |
#' @export |
|
| 86 |
#' @rdname arithmetic |
|
| 87 |
#' @aliases `%power%`,CompositionMatrix,numeric-method |
|
| 88 |
setMethod( |
|
| 89 |
f = "%power%", |
|
| 90 |
signature = c(x = "CompositionMatrix", y = "numeric"), |
|
| 91 |
definition = function(x, y) {
|
|
| 92 | 3x |
arkhe::assert_length(y, 1L) |
| 93 | ||
| 94 | 3x |
z <- closure(x ^ y) |
| 95 | 3x |
z <- methods::initialize(x, z) |
| 96 | 3x |
rownames(z) <- rownames(x) |
| 97 | ||
| 98 | 3x |
z |
| 99 |
} |
|
| 100 |
) |
|
| 101 | ||
| 102 |
#' @export |
|
| 103 |
#' @rdname arithmetic |
|
| 104 |
#' @aliases `%power%`,numeric,CompositionMatrix-method |
|
| 105 |
setMethod( |
|
| 106 |
f = "%power%", |
|
| 107 |
signature = c(x = "numeric", y = "CompositionMatrix"), |
|
| 108 |
definition = function(x, y) {
|
|
| 109 | 1x |
methods::callGeneric(x = y, y = x) |
| 110 |
} |
|
| 111 |
) |
|
| 112 | ||
| 113 |
#' @export |
|
| 114 |
#' @rdname powering |
|
| 115 |
#' @aliases powering,numeric,numeric-method |
|
| 116 |
setMethod( |
|
| 117 |
f = "powering", |
|
| 118 |
signature = c(x = "numeric", a = "numeric"), |
|
| 119 |
definition = function(x, a) {
|
|
| 120 | 1x |
arkhe::assert_length(a, 1L) |
| 121 | 1x |
closure(x ^ a) |
| 122 |
} |
|
| 123 |
) |
|
| 124 | ||
| 125 |
#' @export |
|
| 126 |
#' @rdname powering |
|
| 127 |
#' @aliases powering,numeric,numeric-method |
|
| 128 |
setMethod( |
|
| 129 |
f = "powering", |
|
| 130 |
signature = c(x = "CompositionMatrix", a = "numeric"), |
|
| 131 |
definition = function(x, a) {
|
|
| 132 | 1x |
x %power% a |
| 133 |
} |
|
| 134 |
) |
|
| 135 | ||
| 136 |
# Scalar product =============================================================== |
|
| 137 |
#' @export |
|
| 138 |
#' @rdname scalar |
|
| 139 |
#' @aliases scalar,numeric,numeric-method |
|
| 140 |
setMethod( |
|
| 141 |
f = "scalar", |
|
| 142 |
signature = c(x = "numeric", y = "numeric"), |
|
| 143 |
definition = function(x, y) {
|
|
| 144 | 302x |
n <- length(x) |
| 145 | 302x |
arkhe::assert_length(y, n) |
| 146 | ||
| 147 | 302x |
D <- seq_len(n) |
| 148 | 302x |
z <- 0 |
| 149 | 302x |
for (i in D) {
|
| 150 | 1506x |
j <- utils::tail(D, -i) |
| 151 | 1506x |
z <- z + sum(log(x[i] / x[j]) * log(y[i] / y[j])) |
| 152 |
} |
|
| 153 | 302x |
(1 / n) * z |
| 154 |
} |
|
| 155 |
) |
|
| 156 | ||
| 157 |
#' @export |
|
| 158 |
#' @rdname scalar |
|
| 159 |
#' @aliases scalar,CompositionMatrix,CompositionMatrix-method |
|
| 160 |
setMethod( |
|
| 161 |
f = "scalar", |
|
| 162 |
signature = c(x = "CompositionMatrix", y = "CompositionMatrix"), |
|
| 163 |
definition = function(x, y) {
|
|
| 164 | 1x |
arkhe::assert_dimensions(y, dim(x)) |
| 165 | 1x |
m <- nrow(x) |
| 166 | ||
| 167 | 1x |
z <- numeric(m) |
| 168 | 1x |
for (i in seq_len(m)) {
|
| 169 | 1x |
z[i] <- scalar(x[i, , drop = TRUE], y[i, , drop = TRUE]) |
| 170 |
} |
|
| 171 | 1x |
z |
| 172 |
} |
|
| 173 |
) |
|
| 174 | ||
| 175 |
#' Norm of a Composition |
|
| 176 |
#' |
|
| 177 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 178 |
#' @return A [`numeric`] vector. |
|
| 179 |
#' @keywords internal |
|
| 180 |
#' @noRd |
|
| 181 |
norm <- function(x) {
|
|
| 182 | 300x |
sqrt(scalar(x, x)) |
| 183 |
} |
|
| 184 | ||
| 185 |
#' Aitchison Distance |
|
| 186 |
#' |
|
| 187 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 188 |
#' @param diag A [`logical`] scalar: should the diagonal of the distance matrix |
|
| 189 |
#' be printed? |
|
| 190 |
#' @param upper A [`logical`] scalar: should the upper triangle of the distance |
|
| 191 |
#' matrix be printed? |
|
| 192 |
#' @return A [`dist`] object. |
|
| 193 |
#' @keywords internal |
|
| 194 |
#' @noRd |
|
| 195 |
aitchison <- function(x, diag = FALSE, upper = FALSE) {
|
|
| 196 | 1x |
m <- nrow(x) |
| 197 | 1x |
spl <- rownames(x) |
| 198 | ||
| 199 | 1x |
d <- utils::combn( |
| 200 | 1x |
x = seq_len(m), |
| 201 | 1x |
m = 2, |
| 202 | 1x |
FUN = function(i, coda) {
|
| 203 | 300x |
x <- coda[i[1], , drop = TRUE] |
| 204 | 300x |
y <- coda[i[2], , drop = TRUE] |
| 205 | 300x |
norm(x / y) |
| 206 |
}, |
|
| 207 | 1x |
coda = x |
| 208 |
) |
|
| 209 | ||
| 210 |
## Matrix of results |
|
| 211 | 1x |
mtx <- matrix(data = 0, nrow = m, ncol = m, dimnames = list(spl, spl)) |
| 212 | 1x |
mtx[lower.tri(mtx, diag = FALSE)] <- d |
| 213 | 1x |
mtx <- t(mtx) |
| 214 | 1x |
mtx[lower.tri(mtx, diag = FALSE)] <- d |
| 215 | ||
| 216 | 1x |
stats::as.dist(mtx, diag = diag, upper = upper) |
| 217 |
} |
| 1 |
# HISTOGRAM |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# CompositionMatrix ============================================================ |
|
| 6 |
#' @export |
|
| 7 |
#' @method hist CompositionMatrix |
|
| 8 |
hist.CompositionMatrix <- function(x, ..., select = 1, |
|
| 9 |
breaks = "Sturges", |
|
| 10 |
freq = FALSE, labels = FALSE, |
|
| 11 |
main = NULL, sub = NULL, |
|
| 12 |
ann = graphics::par("ann"),
|
|
| 13 |
axes = TRUE, frame.plot = axes) {
|
|
| 14 |
## Validation |
|
| 15 | 1x |
if (is.character(select)) select <- match(select, labels(x)) |
| 16 | 2x |
arkhe::assert_length(select, 1) |
| 17 | ||
| 18 |
## Graphical parameters |
|
| 19 | 2x |
cex.lab <- list(...)$cex.lab %||% graphics::par("cex.lab")
|
| 20 | 2x |
col.lab <- list(...)$col.lab %||% graphics::par("col.lab")
|
| 21 | 2x |
font.lab <- list(...)$font.lab %||% graphics::par("font.lab")
|
| 22 | 2x |
cex.main <- list(...)$cex.main %||% graphics::par("cex.main")
|
| 23 | 2x |
col.main <- list(...)$col.main %||% graphics::par("col.main")
|
| 24 | 2x |
font.main <- list(...)$font.main %||% graphics::par("font.main")
|
| 25 | ||
| 26 |
## Compute univariate ilr transformation |
|
| 27 | 2x |
z <- univariate_ilr(x) |
| 28 | ||
| 29 |
## Select one compositonal part |
|
| 30 | 2x |
xi <- x[, select, drop = TRUE] |
| 31 | 2x |
zi <- z[, select, drop = TRUE] |
| 32 | ||
| 33 |
## Compute axis in percent |
|
| 34 | 2x |
lab_i <- pretty(xi, n = 6) |
| 35 | 2x |
lab_i <- lab_i[lab_i > 0] |
| 36 | 2x |
at_i <- univariate_ilr(lab_i) |
| 37 | ||
| 38 |
## Plot histogram |
|
| 39 | 2x |
h <- graphics::hist(x = zi, breaks = breaks, plot = FALSE) |
| 40 | 2x |
xlim <- range(at_i, h$breaks, finite = TRUE) |
| 41 | 2x |
plot(h, freq = freq, xlim = xlim, labels = labels, ..., |
| 42 | 2x |
main = main, sub = sub, xlab = NULL, ylab = NULL, axes = FALSE) |
| 43 | ||
| 44 |
## Construct axis |
|
| 45 | 2x |
if (axes) {
|
| 46 | 2x |
graphics::axis(side = 1, xpd = NA, las = 1) |
| 47 | 2x |
graphics::axis(side = 3, at = at_i, labels = label_percent(lab_i), |
| 48 | 2x |
xpd = NA, las = 1) |
| 49 | 2x |
graphics::axis(side = 2, xpd = NA, las = 1) |
| 50 |
} |
|
| 51 | ||
| 52 |
## Plot frame |
|
| 53 | 2x |
if (frame.plot) {
|
| 54 | 2x |
graphics::box() |
| 55 |
} |
|
| 56 | ||
| 57 |
## Add annotation |
|
| 58 | 2x |
if (ann) {
|
| 59 | 2x |
xlab <- labels(x)[select] |
| 60 | 2x |
ylab <- tr_("Frequency")
|
| 61 | 2x |
graphics::mtext(sprintf("ilr(%s)", xlab), side = 1, line = 3,
|
| 62 | 2x |
cex = cex.lab, col = col.lab, font = font.lab) |
| 63 | 2x |
graphics::mtext(sprintf("%s %%", xlab), side = 3, line = 3,
|
| 64 | 2x |
cex = cex.lab, col = col.lab, font = font.lab) |
| 65 | 2x |
graphics::mtext(ylab, side = 2, line = 3, |
| 66 | 2x |
cex = cex.lab, col = col.lab, font = font.lab) |
| 67 |
} |
|
| 68 | ||
| 69 | 2x |
invisible(x) |
| 70 |
} |
|
| 71 | ||
| 72 |
#' @export |
|
| 73 |
#' @rdname hist |
|
| 74 |
#' @aliases hist,CompositionMatrix-method |
|
| 75 |
setMethod("hist", c(x = "CompositionMatrix"), hist.CompositionMatrix)
|
| 1 |
# OUTLIERS |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Find ========================================================================= |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname detect_outlier |
|
| 8 |
#' @aliases detect_outlier,CompositionMatrix,missing-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "detect_outlier", |
|
| 11 |
signature = c(object = "CompositionMatrix", reference = "missing"), |
|
| 12 |
definition = function(object, ..., robust = TRUE, method = c("mve", "mcd"),
|
|
| 13 |
quantile = 0.975) {
|
|
| 14 | 1x |
methods::callGeneric(object, reference = object, robust = robust, |
| 15 | 1x |
method = method, quantile = quantile) |
| 16 |
} |
|
| 17 |
) |
|
| 18 | ||
| 19 |
#' @export |
|
| 20 |
#' @rdname detect_outlier |
|
| 21 |
#' @aliases detect_outlier,CompositionMatrix,CompositionMatrix-method |
|
| 22 |
setMethod( |
|
| 23 |
f = "detect_outlier", |
|
| 24 |
signature = c(object = "CompositionMatrix", reference = "CompositionMatrix"), |
|
| 25 |
definition = function(object, reference, ..., quantile = 0.975, robust = TRUE, |
|
| 26 |
method = c("mve", "mcd")) {
|
|
| 27 |
## Validation |
|
| 28 | 1x |
if (!identical(colnames(object), colnames(reference))) {
|
| 29 | ! |
stop(tr_("Column names do not match!"), call. = FALSE)
|
| 30 |
} |
|
| 31 | ||
| 32 |
## Transformation |
|
| 33 | 1x |
obj <- transform_ilr(object) |
| 34 | 1x |
ref <- transform_ilr(reference) |
| 35 | ||
| 36 |
## Clean |
|
| 37 | 1x |
n <- nrow(ref) |
| 38 | 1x |
p <- ncol(ref) |
| 39 | 1x |
if (n < (p + 1)) {
|
| 40 | ! |
msg <- tr_("Sample size is too small (%d).")
|
| 41 | ! |
stop(sprintf(msg, n), call. = FALSE) |
| 42 |
} |
|
| 43 | 1x |
if (n < (2 * p)) {
|
| 44 | ! |
msg <- tr_("Possibly too small sample size (%d).")
|
| 45 | ! |
warning(sprintf(msg, n), call. = FALSE) |
| 46 |
} |
|
| 47 | ||
| 48 |
## Compute center and spread + Mahalanobis distance |
|
| 49 |
## Standard estimators |
|
| 50 | 1x |
estc <- list(center = colMeans(ref, na.rm = TRUE), cov = cov(ref)) |
| 51 | 1x |
dc <- stats::mahalanobis(obj, center = estc$center, cov = estc$cov) |
| 52 | ||
| 53 |
## Robust estimators |
|
| 54 | 1x |
dr <- rep(NA_real_, nrow(obj)) |
| 55 | 1x |
if (robust) {
|
| 56 | ! |
method <- match.arg(method, several.ok = FALSE) |
| 57 | ! |
estr <- MASS::cov.rob(ref, method = method, ...) |
| 58 | ! |
dr <- stats::mahalanobis(obj, center = estr$center, cov = estr$cov) |
| 59 |
} |
|
| 60 | ||
| 61 |
## Threshold |
|
| 62 | 1x |
limit <- stats::qchisq(p = quantile, df = p) |
| 63 | ||
| 64 | 1x |
.OutlierIndex( |
| 65 | 1x |
samples = rownames(obj), |
| 66 | 1x |
standard = sqrt(dc), |
| 67 | 1x |
robust = sqrt(dr), |
| 68 | 1x |
limit = sqrt(limit), |
| 69 | 1x |
dof = p |
| 70 |
) |
|
| 71 |
} |
|
| 72 |
) |
|
| 73 | ||
| 74 |
#' @export |
|
| 75 |
#' @rdname detect_outlier |
|
| 76 |
#' @aliases is_outlier,OutlierIndex-method |
|
| 77 |
setMethod( |
|
| 78 |
f = "is_outlier", |
|
| 79 |
signature = c("OutlierIndex"),
|
|
| 80 |
definition = function(object, robust = TRUE) {
|
|
| 81 | 1x |
d <- if (robust) object@robust else object@standard |
| 82 | 1x |
out <- d > object@limit |
| 83 | 1x |
names(out) <- object@samples |
| 84 | 1x |
out |
| 85 |
} |
|
| 86 |
) |
|
| 87 | ||
| 88 |
# Plot ========================================================================= |
|
| 89 |
#' @export |
|
| 90 |
#' @method plot OutlierIndex |
|
| 91 |
plot.OutlierIndex <- function(x, ..., |
|
| 92 |
type = c("dotchart", "distance"),
|
|
| 93 |
robust = TRUE, |
|
| 94 |
symbols = c(16, 1, 3), |
|
| 95 |
xlim = NULL, ylim = NULL, |
|
| 96 |
xlab = NULL, ylab = NULL, |
|
| 97 |
main = NULL, sub = NULL, |
|
| 98 |
ann = graphics::par("ann"),
|
|
| 99 |
axes = TRUE, frame.plot = axes, |
|
| 100 |
panel.first = NULL, panel.last = NULL, |
|
| 101 |
legend = list(x = "topleft")) {
|
|
| 102 |
## Get data |
|
| 103 | 1x |
dc <- x@standard |
| 104 | 1x |
dr <- x@robust |
| 105 | 1x |
dof <- x@dof |
| 106 | 1x |
limit <- x@limit |
| 107 | 1x |
n <- length(dc) |
| 108 | ||
| 109 |
## Validation |
|
| 110 | 1x |
if (all(is.na(dr))) {
|
| 111 | 1x |
robust <- FALSE |
| 112 | 1x |
type <- "dotchart" |
| 113 |
} |
|
| 114 | 1x |
type <- match.arg(type, several.ok = FALSE) |
| 115 | ||
| 116 |
## Graphical parameters |
|
| 117 | 1x |
shape <- rep(symbols[[1L]], n) |
| 118 | ! |
if (robust || type == "distance") shape[dr > limit] <- symbols[[3L]] |
| 119 | 1x |
if (!robust || type == "distance") shape[dc > limit] <- symbols[[2L]] |
| 120 | ||
| 121 | 1x |
cy <- if (robust) dr else dc |
| 122 | 1x |
dlab <- ifelse(robust, tr_("Robust Mahalanobis distance"),
|
| 123 | 1x |
tr_("Standard Mahalanobis distance"))
|
| 124 | 1x |
ylab <- ylab %||% dlab |
| 125 | ||
| 126 | 1x |
if (type == "dotchart") {
|
| 127 | 1x |
asp <- NA |
| 128 | 1x |
cx <- seq_along(dc) |
| 129 | 1x |
xlab <- xlab %||% tr_("Index")
|
| 130 | 1x |
panel <- function() {
|
| 131 | 1x |
graphics::points(x = cx, y = cy, pch = shape, ...) |
| 132 | 1x |
graphics::abline(h = limit, lty = 1) |
| 133 |
} |
|
| 134 |
} |
|
| 135 | 1x |
if (type == "distance") {
|
| 136 | ! |
asp <- 1 |
| 137 | ! |
cx <- dc |
| 138 | ! |
cy <- dr |
| 139 | ! |
xlab <- xlab %||% tr_("Standard Mahalanobis distance")
|
| 140 | ! |
ylab <- ylab %||% tr_("Robust Mahalanobis distance")
|
| 141 | ! |
panel <- function() {
|
| 142 | ! |
graphics::points(x = cx, y = cy, pch = shape, ...) |
| 143 | ! |
graphics::abline(h = limit, lty = 1) |
| 144 | ! |
graphics::abline(v = limit, lty = 1) |
| 145 | ! |
graphics::abline(a = 0, b = 1, lty = 2, col = "darkgrey") |
| 146 |
} |
|
| 147 |
} |
|
| 148 | ||
| 149 |
## Open new window |
|
| 150 | 1x |
grDevices::dev.hold() |
| 151 | 1x |
on.exit(grDevices::dev.flush(), add = TRUE) |
| 152 | 1x |
graphics::plot.new() |
| 153 | ||
| 154 |
## Set plotting coordinates |
|
| 155 | 1x |
xlim <- xlim %||% range(cx, finite = TRUE) |
| 156 | 1x |
ylim <- ylim %||% range(cy, finite = TRUE) |
| 157 | 1x |
graphics::plot.window(xlim = xlim, ylim = ylim, asp = asp) |
| 158 | ||
| 159 |
## Evaluate pre-plot expressions |
|
| 160 | 1x |
panel.first |
| 161 | ||
| 162 |
## Plot |
|
| 163 | 1x |
panel() |
| 164 | ||
| 165 |
## Evaluate post-plot and pre-axis expressions |
|
| 166 | 1x |
panel.last |
| 167 | ||
| 168 |
## Construct Axis |
|
| 169 | 1x |
if (axes) {
|
| 170 | 1x |
graphics::axis(side = 1, las = 1) |
| 171 | 1x |
graphics::axis(side = 2, las = 1) |
| 172 |
} |
|
| 173 | ||
| 174 |
## Plot frame |
|
| 175 | 1x |
if (frame.plot) {
|
| 176 | 1x |
graphics::box() |
| 177 |
} |
|
| 178 | ||
| 179 |
## Add annotation |
|
| 180 | 1x |
if (ann) {
|
| 181 | 1x |
graphics::title(main = main, sub = sub, xlab = xlab, ylab = ylab) |
| 182 |
} |
|
| 183 | ||
| 184 |
## Add legend |
|
| 185 | 1x |
if (is.list(legend)) {
|
| 186 | 1x |
if (type == "distance") {
|
| 187 | ! |
lab <- c(tr_("No outlier"), tr_("Robust only"), tr_("Both"))
|
| 188 | ! |
pch <- symbols |
| 189 |
} else {
|
|
| 190 | 1x |
lab <- c(tr_("No outlier"), tr_("Outlier"))
|
| 191 | 1x |
pch <- symbols[-2 - !robust] |
| 192 |
} |
|
| 193 | 1x |
args <- list(x = "topleft", legend = lab, pch = pch, bty = "n", xpd = NA) |
| 194 | 1x |
args <- utils::modifyList(args, legend) |
| 195 | 1x |
do.call(graphics::legend, args = args) |
| 196 |
} |
|
| 197 | ||
| 198 | 1x |
invisible(x) |
| 199 |
} |
|
| 200 | ||
| 201 |
#' @export |
|
| 202 |
#' @rdname plot_outlier |
|
| 203 |
#' @aliases plot,OutlierIndex,missing-method |
|
| 204 |
setMethod("plot", c(x = "OutlierIndex", y = "missing"), plot.OutlierIndex)
|
| 1 |
# BOXPLOT |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# LogRatio ===================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @method boxplot LogRatio |
|
| 8 |
boxplot.LogRatio <- function(x, ..., range = 1.5, width = NULL, varwidth = FALSE, |
|
| 9 |
notch = FALSE, outline = TRUE, |
|
| 10 |
plot = TRUE, horizontal = FALSE, |
|
| 11 |
xlab = NULL, ylab = NULL, main = NULL, sub = NULL, |
|
| 12 |
ann = graphics::par("ann")) {
|
|
| 13 | 1x |
z <- as.data.frame(x) |
| 14 | 1x |
if (horizontal) {
|
| 15 | ! |
xlab <- xlab %||% get_transformation(x) |
| 16 |
} else {
|
|
| 17 | 1x |
ylab <- ylab %||% get_transformation(x) |
| 18 |
} |
|
| 19 | 1x |
box <- graphics::boxplot(z, ..., range = range, width = width, |
| 20 | 1x |
varwidth = varwidth, notch = notch, outline = outline, |
| 21 | 1x |
names = labels(x), plot = plot, horizontal = horizontal, |
| 22 | 1x |
xlab = xlab, ylab = ylab, main = main, sub = sub, |
| 23 | 1x |
ann = ann, log = "", las = 1) |
| 24 | ! |
if (!plot) return(invisible(box)) |
| 25 | ||
| 26 | 1x |
invisible(x) |
| 27 |
} |
|
| 28 | ||
| 29 |
#' @export |
|
| 30 |
#' @rdname boxplot |
|
| 31 |
#' @aliases boxplot,LogRatio-method |
|
| 32 |
setMethod("boxplot", c(x = "LogRatio"), boxplot.LogRatio)
|
|
| 33 | ||
| 34 |
# GroupedLogRatio ============================================================== |
|
| 35 |
#' @export |
|
| 36 |
#' @method boxplot GroupedLogRatio |
|
| 37 |
boxplot.GroupedLogRatio <- function(x, ..., range = 1.5, width = NULL, |
|
| 38 |
varwidth = FALSE, notch = FALSE, |
|
| 39 |
outline = TRUE, plot = TRUE, |
|
| 40 |
horizontal = FALSE, color = NULL, |
|
| 41 |
xlab = NULL, ylab = NULL, |
|
| 42 |
main = NULL, sub = NULL, |
|
| 43 |
ann = graphics::par("ann"),
|
|
| 44 |
legend = list(x = "topright")) {
|
|
| 45 |
## Graphical parameters |
|
| 46 | 1x |
lvl <- group_levels(x) |
| 47 | 1x |
col <- khroma::palette_color_discrete(color)(lvl) |
| 48 | 1x |
bg <- grDevices::adjustcolor(col, alpha.f = 0.5) |
| 49 | 1x |
cex.axis <- list(...)$cex.axis %||% graphics::par("cex.axis")
|
| 50 | 1x |
col.axis <- list(...)$col.axis %||% graphics::par("col.axis")
|
| 51 | 1x |
font.axis <- list(...)$font.axis %||% graphics::par("font.axis")
|
| 52 | ||
| 53 |
## Prepare data |
|
| 54 | 1x |
df <- data.frame( |
| 55 | 1x |
x = as.numeric(x), |
| 56 | 1x |
y = interaction( |
| 57 | 1x |
factor(rep(labels(x), each = nrow(x)), levels = labels(x)), |
| 58 | 1x |
factor(rep(group_names(x), times = ncol(x)), levels = group_levels(x)), |
| 59 | 1x |
lex.order = TRUE |
| 60 |
) |
|
| 61 |
) |
|
| 62 | ||
| 63 |
## Plot |
|
| 64 | 1x |
box <- graphics::boxplot( |
| 65 | 1x |
formula = x ~ y, data = df, ..., |
| 66 | 1x |
range = range, |
| 67 | 1x |
width = width, |
| 68 | 1x |
varwidth = varwidth, |
| 69 | 1x |
notch = notch, |
| 70 | 1x |
outline = outline, |
| 71 | 1x |
plot = plot, |
| 72 | 1x |
border = col, |
| 73 | 1x |
col = bg, |
| 74 | 1x |
horizontal = horizontal, |
| 75 | 1x |
log = "", |
| 76 | 1x |
ann = FALSE, |
| 77 | 1x |
xaxt = ifelse(!horizontal, "n", "s"), |
| 78 | 1x |
yaxt = ifelse(horizontal, "n", "s"), |
| 79 | 1x |
las = 1 |
| 80 |
) |
|
| 81 | ! |
if (!plot) return(invisible(box)) |
| 82 | ||
| 83 |
## Add annotation |
|
| 84 | 1x |
if (ann) {
|
| 85 | 1x |
if (horizontal) {
|
| 86 | ! |
xlab <- xlab %||% get_transformation(x) |
| 87 |
} else {
|
|
| 88 | 1x |
ylab <- ylab %||% get_transformation(x) |
| 89 |
} |
|
| 90 | 1x |
graphics::title(main = main, sub = sub, xlab = xlab, ylab = ylab) |
| 91 |
} |
|
| 92 | ||
| 93 |
## Construct axis |
|
| 94 | 1x |
n_group <- length(group_levels(x)) |
| 95 | 1x |
graphics::axis( |
| 96 | 1x |
side = ifelse(horizontal, 2, 1), |
| 97 | 1x |
at = seq(from = (n_group + 1) / 2, to = ncol(x) * n_group, by = n_group), |
| 98 | 1x |
labels = labels(x), |
| 99 | 1x |
cex.axis = cex.axis, |
| 100 | 1x |
col.axis = col.axis, |
| 101 | 1x |
font.axis = font.axis, |
| 102 | 1x |
las = 1 |
| 103 |
) |
|
| 104 | ||
| 105 |
## Add legend |
|
| 106 | 1x |
if (is.list(legend) && length(legend) > 0) {
|
| 107 | 1x |
args <- list(x = "topright", legend = lvl, fill = col, bty = "n") |
| 108 | 1x |
args <- utils::modifyList(args, legend) |
| 109 | 1x |
do.call(graphics::legend, args = args) |
| 110 |
} |
|
| 111 | ||
| 112 | 1x |
invisible(x) |
| 113 |
} |
|
| 114 | ||
| 115 |
#' @export |
|
| 116 |
#' @rdname boxplot |
|
| 117 |
#' @aliases boxplot,GroupedLogRatio-method |
|
| 118 |
setMethod("boxplot", c(x = "GroupedLogRatio"), boxplot.GroupedLogRatio)
|
| 1 |
# SHOW |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
setMethod( |
|
| 6 |
f = "show", |
|
| 7 |
signature = "CompositionMatrix", |
|
| 8 |
definition = function(object) {
|
|
| 9 | 4x |
m <- nrow(object) |
| 10 | 4x |
p <- ncol(object) |
| 11 | 4x |
mtx <- methods::as(object, "matrix") |
| 12 | ||
| 13 | 4x |
txt_dim <- sprintf("%d x %d", m, p)
|
| 14 | 4x |
txt_mtx <- sprintf("<%s: %s>", class(object), txt_dim)
|
| 15 | ||
| 16 | 4x |
cat( |
| 17 | 4x |
txt_mtx, |
| 18 | 4x |
utils::capture.output(mtx), |
| 19 | 4x |
sep = "\n" |
| 20 |
) |
|
| 21 | 4x |
invisible(object) |
| 22 |
} |
|
| 23 |
) |
|
| 24 | ||
| 25 |
setMethod( |
|
| 26 |
f = "show", |
|
| 27 |
signature = "LogRatio", |
|
| 28 |
definition = function(object) {
|
|
| 29 | ! |
m <- nrow(object) |
| 30 | ! |
p <- ncol(object) |
| 31 | ! |
mtx <- methods::as(object, "matrix") |
| 32 | ||
| 33 | ! |
txt_dim <- sprintf("%d x %d", m, p)
|
| 34 | ! |
txt_mtx <- sprintf("<%s: %s>", get_transformation(object), txt_dim)
|
| 35 | ||
| 36 | ! |
cat( |
| 37 | ! |
txt_mtx, |
| 38 | ! |
utils::capture.output(mtx), |
| 39 | ! |
sep = "\n" |
| 40 |
) |
|
| 41 | ! |
invisible(object) |
| 42 |
} |
|
| 43 |
) |
| 1 |
# GRAPH |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @rdname as_graph |
|
| 7 |
#' @aliases as_graph,LR-method |
|
| 8 |
setMethod( |
|
| 9 |
f = "as_graph", |
|
| 10 |
signature = c(object = "LR"), |
|
| 11 |
definition = function(object) {
|
|
| 12 |
## Validation |
|
| 13 | ! |
arkhe::assert_package("igraph")
|
| 14 | ||
| 15 | ! |
ratio <- labels(object) |
| 16 | ! |
edges <- do.call(rbind, strsplit(ratio, "/")) |
| 17 | ! |
edges <- edges[, c(2, 1)] |
| 18 | ! |
igraph::graph_from_edgelist(edges, directed = FALSE) |
| 19 |
} |
|
| 20 |
) |
|
| 21 | ||
| 22 |
#' @export |
|
| 23 |
#' @rdname as_graph |
|
| 24 |
#' @aliases as_graph,ALR-method |
|
| 25 |
setMethod( |
|
| 26 |
f = "as_graph", |
|
| 27 |
signature = c(object = "ALR"), |
|
| 28 |
definition = function(object) {
|
|
| 29 |
## Validation |
|
| 30 | ! |
arkhe::assert_package("igraph")
|
| 31 | ||
| 32 | ! |
ratio <- labels(object) |
| 33 | ! |
edges <- do.call(rbind, strsplit(ratio, "/")) |
| 34 | ! |
edges <- edges[, c(2, 1)] |
| 35 | ! |
igraph::graph_from_edgelist(edges, directed = TRUE) |
| 36 |
} |
|
| 37 |
) |
|
| 38 | ||
| 39 |
#' @export |
|
| 40 |
#' @rdname as_graph |
|
| 41 |
#' @aliases as_graph,ILR-method |
|
| 42 |
setMethod( |
|
| 43 |
f = "as_graph", |
|
| 44 |
signature = c(object = "ILR"), |
|
| 45 |
definition = function(object) {
|
|
| 46 |
## Validation |
|
| 47 | ! |
arkhe::assert_package("igraph")
|
| 48 | ||
| 49 | ! |
ratio <- labels(object) |
| 50 | ! |
ratio <- gsub(pattern = "[\\(\\)]", replacement = "", x = ratio) |
| 51 | ! |
edges <- lapply( |
| 52 | ! |
X = strsplit(ratio, "/"), |
| 53 | ! |
FUN = function(x) {
|
| 54 | ! |
a <- unlist(strsplit(x[[1]], ",")) |
| 55 | ! |
b <- unlist(strsplit(x[[2]], ",")) |
| 56 | ! |
expand.grid(b, a) |
| 57 |
} |
|
| 58 |
) |
|
| 59 | ! |
edges <- do.call(rbind, edges) |
| 60 | ! |
igraph::graph_from_data_frame(edges, directed = TRUE) |
| 61 |
} |
|
| 62 |
) |
| 1 |
# DATA SUMMARY: DESCRIBE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @rdname describe |
|
| 7 |
#' @aliases describe,CompositionMatrix-method |
|
| 8 |
setMethod( |
|
| 9 |
f = "describe", |
|
| 10 |
signature = c(x = "CompositionMatrix"), |
|
| 11 |
definition = function(x) {
|
|
| 12 |
## Variables |
|
| 13 | 1x |
msg_parts <- describe_coda(x) |
| 14 | ||
| 15 |
## Missing values |
|
| 16 | 1x |
msg_miss <- describe_missing(x) |
| 17 | ||
| 18 |
## Check |
|
| 19 | 1x |
msg_val <- describe_check(x) |
| 20 | ||
| 21 | 1x |
cat(msg_parts, msg_miss, msg_val, sep = "\n") |
| 22 | ||
| 23 | 1x |
invisible(x) |
| 24 |
} |
|
| 25 |
) |
|
| 26 | ||
| 27 |
#' @export |
|
| 28 |
#' @rdname describe |
|
| 29 |
#' @aliases describe,GroupedComposition-method |
|
| 30 |
setMethod( |
|
| 31 |
f = "describe", |
|
| 32 |
signature = c(x = "GroupedComposition"), |
|
| 33 |
definition = function(x) {
|
|
| 34 |
## Variables |
|
| 35 | 1x |
msg_parts <- describe_coda(x) |
| 36 | ||
| 37 |
## Groups |
|
| 38 | 1x |
msg_group <- describe_groups(x) |
| 39 | ||
| 40 |
## Missing values |
|
| 41 | 1x |
msg_miss <- describe_missing(x) |
| 42 | ||
| 43 |
## Check |
|
| 44 | 1x |
msg_val <- describe_check(x) |
| 45 | ||
| 46 | 1x |
cat(paste0(msg_parts, msg_group), msg_miss, msg_val, sep = "\n") |
| 47 | ||
| 48 | 1x |
invisible(x) |
| 49 |
} |
|
| 50 |
) |
|
| 51 | ||
| 52 |
describe_coda <- function(x) {
|
|
| 53 | 2x |
m <- nrow(x) |
| 54 | 2x |
p <- ncol(x) |
| 55 | ||
| 56 | 2x |
rows <- sprintf(ngettext(m, "%d composition", "%d compositions"), m) |
| 57 | 2x |
title <- sprintf("%s:", rows)
|
| 58 | ||
| 59 | 2x |
cols <- paste0(dQuote(labels(x)), collapse = ", ") |
| 60 | 2x |
msg <- sprintf(ngettext(p, "%d part", "%d parts"), p) |
| 61 | 2x |
msg <- sprintf("\n* %s: %s.", msg, cols)
|
| 62 | ||
| 63 | 2x |
paste0(title, msg, collapse = "") |
| 64 |
} |
|
| 65 |
describe_groups <- function(x) {
|
|
| 66 | ||
| 67 | 1x |
i <- group_n(x) |
| 68 | 1x |
ls_grp <- paste0(dQuote(group_levels(x)), collapse = ", ") |
| 69 | 1x |
msg_grp <- sprintf(ngettext(i, "%d group", "%d groups"), i) |
| 70 | 1x |
msg_grp <- sprintf("%s: %s", msg_grp, ls_grp)
|
| 71 | ||
| 72 | 1x |
j <- sum(!is_assigned(x)) |
| 73 | 1x |
msg_ung <- sprintf(ngettext(j, "%d unassigned sample", "%d unassigned samples"), j) |
| 74 | ||
| 75 | 1x |
paste0(sprintf("\n* %s.", c(msg_grp, msg_ung)), collapse = "")
|
| 76 |
} |
|
| 77 |
describe_missing <- function(x) {
|
|
| 78 | 2x |
m <- nrow(x) |
| 79 | 2x |
p <- ncol(x) |
| 80 | ||
| 81 | 2x |
n_NA <- sum(count(x, f = is.na)) |
| 82 | 2x |
m_NA <- sum(detect(x, f = is.na, margin = 1)) |
| 83 | 2x |
p_NA <- sum(detect(x, f = is.na, margin = 2)) |
| 84 | 2x |
pc <- label_percent(c(m_NA / m, p_NA / p), digits = 1, trim = TRUE) |
| 85 | ||
| 86 | 2x |
title <- sprintf(ngettext(n_NA, "%d missing value:", "%d missing values:"), n_NA) |
| 87 | ||
| 88 | 2x |
rows_NA <- ngettext(m_NA, "%d observation (%s) contains missing values", |
| 89 | 2x |
"%d observations (%s) contain missing values") |
| 90 | 2x |
msg_row_NA <- sprintf(rows_NA, m_NA, pc[[1]]) |
| 91 | ||
| 92 | 2x |
cols_NA <- ngettext(p_NA, "%d variable (%s) contains missing values", |
| 93 | 2x |
"%d variables (%s) contain missing values") |
| 94 | 2x |
msg_col_NA <- sprintf(cols_NA, p_NA, pc[[2]]) |
| 95 | ||
| 96 | 2x |
msg <- paste0(sprintf("\n* %s.", c(msg_row_NA, msg_col_NA)), collapse = "")
|
| 97 | 2x |
paste0("\n", title, msg, collapse = "")
|
| 98 |
} |
|
| 99 |
describe_check <- function(x) {
|
|
| 100 | 2x |
title <- tr_("Data checking:")
|
| 101 | ||
| 102 |
## Constant columns |
|
| 103 | 2x |
p_var <- sum(detect(x, f = function(x) is_unique(x), margin = 2)) |
| 104 | 2x |
cols_var <- ngettext(p_var, "%d variable with no variance", |
| 105 | 2x |
"%d variables with no variance") |
| 106 | 2x |
msg_col_var <- sprintf(cols_var, p_var) |
| 107 | ||
| 108 |
## Sparsity |
|
| 109 | 2x |
spa <- sparsity(x, count = FALSE) |
| 110 | 2x |
msg_spa <- sprintf(tr_("%s of numeric values are zero"), label_percent(spa, digits = 1))
|
| 111 | ||
| 112 | 2x |
msg <- paste0(sprintf("\n* %s.", c(msg_spa, msg_col_var)), collapse = "")
|
| 113 | 2x |
paste0("\n", title, msg, collapse = "")
|
| 114 |
} |
| 1 |
# PLOT |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# LogRatio ===================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @method plot LogRatio |
|
| 8 |
plot.LogRatio <- function(x, ..., jitter_factor = 1, jitter_amount = NULL, |
|
| 9 |
xlab = NULL, ylab = NULL, |
|
| 10 |
main = NULL, sub = NULL, ann = graphics::par("ann"),
|
|
| 11 |
axes = TRUE, frame.plot = axes) {
|
|
| 12 |
## Get data |
|
| 13 | 2x |
xy <- data.frame( |
| 14 | 2x |
x = jitter(as.vector(col(x)), factor = jitter_factor, amount = jitter_amount), |
| 15 | 2x |
y = as.vector(x) |
| 16 |
) |
|
| 17 | ||
| 18 |
## Graphical parameters |
|
| 19 | 2x |
col <- list(...)$col %||% graphics::par("col")
|
| 20 | 2x |
bg <- list(...)$bg %||% graphics::par("bg")
|
| 21 | 2x |
pch <- list(...)$pch %||% graphics::par("pch")
|
| 22 | 2x |
cex.axis <- list(...)$cex.axis %||% graphics::par("cex.axis")
|
| 23 | 2x |
col.axis <- list(...)$col.axis %||% graphics::par("col.axis")
|
| 24 | 2x |
font.axis <- list(...)$font.axis %||% graphics::par("font.axis")
|
| 25 | ||
| 26 |
## Open new window |
|
| 27 | 2x |
grDevices::dev.hold() |
| 28 | 2x |
on.exit(grDevices::dev.flush(), add = TRUE) |
| 29 | 2x |
graphics::plot.new() |
| 30 | ||
| 31 |
## Set plotting coordinates |
|
| 32 | 2x |
xlim <- range(xy$x) |
| 33 | 2x |
ylim <- range(xy$y) |
| 34 | 2x |
graphics::plot.window(xlim = xlim, ylim = ylim) |
| 35 | ||
| 36 |
## Plot |
|
| 37 | 2x |
graphics::points(x = xy$x, y = xy$y, pch = pch, col = col, bg = bg) |
| 38 | ||
| 39 |
## Construct axis |
|
| 40 | 2x |
if (axes) {
|
| 41 | 2x |
graphics::axis(side = 1, at = seq_len(ncol(x)), |
| 42 | 2x |
labels = labels(x), las = 1, |
| 43 | 2x |
cex.axis = cex.axis, col.axis = col.axis, |
| 44 | 2x |
font.axis = font.axis) |
| 45 | 2x |
graphics::axis(side = 2, las = 1) |
| 46 |
} |
|
| 47 | ||
| 48 |
## Plot frame |
|
| 49 | 2x |
if (frame.plot) {
|
| 50 | 2x |
graphics::box() |
| 51 |
} |
|
| 52 | ||
| 53 |
## Add annotation |
|
| 54 | 2x |
if (ann) {
|
| 55 | 2x |
ylab <- ylab %||% get_transformation(x) |
| 56 | 2x |
graphics::title(main = main, sub = sub, xlab = xlab, ylab = ylab) |
| 57 |
} |
|
| 58 | ||
| 59 | 2x |
invisible(x) |
| 60 |
} |
|
| 61 | ||
| 62 |
#' @export |
|
| 63 |
#' @rdname plot |
|
| 64 |
#' @aliases plot,LogRatio,missing-method |
|
| 65 |
setMethod("plot", c(x = "LogRatio", y = "missing"), plot.LogRatio)
|
|
| 66 | ||
| 67 |
#' @export |
|
| 68 |
#' @method plot GroupedLogRatio |
|
| 69 |
plot.GroupedLogRatio <- function(x, ..., jitter_factor = 1, jitter_amount = NULL, |
|
| 70 |
color = NULL, symbol = NULL, |
|
| 71 |
xlab = NULL, ylab = NULL, |
|
| 72 |
main = NULL, sub = NULL, |
|
| 73 |
ann = graphics::par("ann"),
|
|
| 74 |
axes = TRUE, frame.plot = axes, |
|
| 75 |
legend = list(x = "topright")) {
|
|
| 76 | ||
| 77 |
## Graphical parameters |
|
| 78 | 1x |
lvl <- group_names(x) |
| 79 | 1x |
col <- khroma::palette_color_discrete(color)(lvl) |
| 80 | 1x |
bg <- grDevices::adjustcolor(col, alpha.f = 0.5) |
| 81 | 1x |
pch <- khroma::palette_shape(symbol)(lvl) |
| 82 | ||
| 83 |
## Plot |
|
| 84 | 1x |
plot( |
| 85 | 1x |
ungroup(x), |
| 86 | 1x |
col = col, pch = pch, bg = bg, |
| 87 | 1x |
jitter_factor = jitter_factor, |
| 88 | 1x |
jitter_amount = jitter_amount, |
| 89 | 1x |
xlab = xlab, ylab = ylab, |
| 90 | 1x |
main = main, sub = sub, ann = ann, |
| 91 | 1x |
axes = axes, frame.plot = frame.plot |
| 92 |
) |
|
| 93 | ||
| 94 |
## Add legend |
|
| 95 | 1x |
if (is.list(legend) && is_grouped(x)) {
|
| 96 | 1x |
args <- list( |
| 97 | 1x |
x = "topright", |
| 98 | 1x |
legend = tapply(lvl, lvl, unique), |
| 99 | 1x |
pch = tapply(pch, lvl, unique), |
| 100 | 1x |
col = tapply(col, lvl, unique), |
| 101 | 1x |
bg = tapply(bg, lvl, unique), |
| 102 | 1x |
bty = "n" |
| 103 |
) |
|
| 104 | 1x |
args <- utils::modifyList(args, legend) |
| 105 | 1x |
do.call(graphics::legend, args = args) |
| 106 |
} |
|
| 107 | ||
| 108 | 1x |
invisible(x) |
| 109 |
} |
|
| 110 | ||
| 111 |
#' @export |
|
| 112 |
#' @rdname plot |
|
| 113 |
#' @aliases plot,GroupedLogRatio,missing-method |
|
| 114 |
setMethod("plot", c(x = "GroupedLogRatio", y = "missing"), plot.GroupedLogRatio)
|
| 1 |
# DATA TRANSFORMATION: ISOMETRIC LOG RATIO |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# ILR ========================================================================== |
|
| 6 |
ilr_base <- function(D, method = "basic") {
|
|
| 7 |
## Validation |
|
| 8 | 11x |
method <- match.arg(method, several.ok = FALSE) |
| 9 | ||
| 10 | 11x |
seq_parts <- seq_len(D - 1) |
| 11 | ||
| 12 |
## Original ILR transformation defined by Egozcue et al. 2003 |
|
| 13 | 11x |
if (method == "basic") {
|
| 14 |
## Helmert matrix (rotation matrix) |
|
| 15 | 11x |
H <- stats::contr.helmert(D) # D x D-1 |
| 16 | 11x |
H <- t(H) / sqrt((seq_parts + 1) * seq_parts) # D-1 x D |
| 17 | ||
| 18 |
## Center |
|
| 19 | 11x |
M <- diag(x = 1, nrow = D) - matrix(data = 1 / D, nrow = D, ncol = D) |
| 20 | 11x |
V <- tcrossprod(M, H) |
| 21 |
} |
|
| 22 | ||
| 23 | 11x |
V |
| 24 |
} |
|
| 25 | ||
| 26 |
#' @export |
|
| 27 |
#' @rdname transform_ilr |
|
| 28 |
#' @aliases transform_ilr,CompositionMatrix,missing-method |
|
| 29 |
setMethod( |
|
| 30 |
f = "transform_ilr", |
|
| 31 |
signature = c(object = "CompositionMatrix"), |
|
| 32 |
definition = function(object) {
|
|
| 33 | 8x |
weights <- rep(1 / ncol(object), ncol(object)) |
| 34 | 8x |
base <- ilr_base(D = ncol(object), method = "basic") |
| 35 | 8x |
.transform_ilr(object, base, weights) |
| 36 |
} |
|
| 37 |
) |
|
| 38 | ||
| 39 |
#' @export |
|
| 40 |
#' @rdname transform_ilr |
|
| 41 |
#' @aliases transform_ilr,GroupedComposition,missing-method |
|
| 42 |
setMethod( |
|
| 43 |
f = "transform_ilr", |
|
| 44 |
signature = c(object = "GroupedComposition"), |
|
| 45 |
definition = function(object) {
|
|
| 46 | 1x |
z <- methods::callNextMethod() |
| 47 | 1x |
.GroupedILR(z, group_indices = group_indices(object), |
| 48 | 1x |
group_levels = group_levels(object), |
| 49 | 1x |
group_ordered = is_ordered(object)) |
| 50 |
} |
|
| 51 |
) |
|
| 52 | ||
| 53 |
#' @export |
|
| 54 |
#' @rdname transform_ilr |
|
| 55 |
#' @aliases transform_ilr,CLR,missing-method |
|
| 56 |
setMethod( |
|
| 57 |
f = "transform_ilr", |
|
| 58 |
signature = c(object = "CLR"), |
|
| 59 |
definition = function(object) {
|
|
| 60 | 2x |
weights <- object@weights |
| 61 | 2x |
base <- ilr_base(D = ncol(object), method = "basic") |
| 62 | 2x |
object@.Data <- exp(object@.Data) |
| 63 | 2x |
.transform_ilr(object, base, weights) |
| 64 |
} |
|
| 65 |
) |
|
| 66 | ||
| 67 |
#' @export |
|
| 68 |
#' @rdname transform_ilr |
|
| 69 |
#' @aliases transform_ilr,GroupedCLR,missing-method |
|
| 70 |
setMethod( |
|
| 71 |
f = "transform_ilr", |
|
| 72 |
signature = c(object = "GroupedCLR"), |
|
| 73 |
definition = function(object) {
|
|
| 74 | ! |
z <- methods::callNextMethod() |
| 75 | ! |
.GroupedILR(z, group_indices = group_indices(object), |
| 76 | ! |
group_levels = group_levels(object), |
| 77 | ! |
group_ordered = is_ordered(object)) |
| 78 |
} |
|
| 79 |
) |
|
| 80 | ||
| 81 |
#' @export |
|
| 82 |
#' @rdname transform_ilr |
|
| 83 |
#' @aliases transform_ilr,ALR,missing-method |
|
| 84 |
setMethod( |
|
| 85 |
f = "transform_ilr", |
|
| 86 |
signature = c(object = "ALR"), |
|
| 87 |
definition = function(object) {
|
|
| 88 | 1x |
object <- transform_clr(object) |
| 89 | 1x |
methods::callGeneric(object) |
| 90 |
} |
|
| 91 |
) |
|
| 92 | ||
| 93 |
#' @export |
|
| 94 |
#' @rdname transform_ilr |
|
| 95 |
#' @aliases transform_ilr,GroupedALR,missing-method |
|
| 96 |
setMethod( |
|
| 97 |
f = "transform_ilr", |
|
| 98 |
signature = c(object = "GroupedALR"), |
|
| 99 |
definition = function(object) {
|
|
| 100 | ! |
z <- methods::callNextMethod() |
| 101 | ! |
.GroupedILR(z, group_indices = group_indices(object), |
| 102 | ! |
group_levels = group_levels(object), |
| 103 | ! |
group_ordered = is_ordered(object)) |
| 104 |
} |
|
| 105 |
) |
|
| 106 | ||
| 107 |
.transform_ilr <- function(object, base, weights) {
|
|
| 108 | 10x |
D <- ncol(object) |
| 109 | 10x |
seq_parts <- seq_len(D - 1) |
| 110 | 10x |
parts <- colnames(object) |
| 111 | ||
| 112 |
## Rotated and centered values |
|
| 113 | 10x |
y <- log(object, base = exp(1)) |
| 114 | 10x |
ilr <- y %*% base |
| 115 | ||
| 116 | 10x |
ratio <- vapply( |
| 117 | 10x |
X = seq_parts, |
| 118 | 10x |
FUN = function(i, k) {
|
| 119 | 32x |
sprintf("(%s)/%s", paste0(k[seq_len(i)], collapse = ","), k[i + 1])
|
| 120 |
}, |
|
| 121 | 10x |
FUN.VALUE = character(1), |
| 122 | 10x |
k = parts |
| 123 |
) |
|
| 124 | 10x |
colnames(ilr) <- paste0("Z", seq_parts)
|
| 125 | 10x |
rownames(ilr) <- rownames(object) |
| 126 | ||
| 127 | 10x |
.ILR( |
| 128 | 10x |
ilr, |
| 129 | 10x |
parts = parts, |
| 130 | 10x |
ratio = ratio, |
| 131 | 10x |
order = seq_len(D), |
| 132 | 10x |
base = base, |
| 133 | 10x |
weights = weights, |
| 134 | 10x |
totals = totals(object) |
| 135 |
) |
|
| 136 |
} |
|
| 137 | ||
| 138 |
# Univariate ILR =============================================================== |
|
| 139 |
#' @export |
|
| 140 |
#' @rdname univariate_ilr |
|
| 141 |
#' @aliases univariate_ilr,numeric-method |
|
| 142 |
setMethod( |
|
| 143 |
f = "univariate_ilr", |
|
| 144 |
signature = c(object = "numeric"), |
|
| 145 |
definition = function(object) {
|
|
| 146 | 12x |
sqrt(1 / 2) * log(object / (1 - object)) |
| 147 |
} |
|
| 148 |
) |
|
| 149 | ||
| 150 |
#' @export |
|
| 151 |
#' @rdname univariate_ilr |
|
| 152 |
#' @aliases univariate_ilr,matrix-method |
|
| 153 |
setMethod( |
|
| 154 |
f = "univariate_ilr", |
|
| 155 |
signature = c(object = "matrix"), |
|
| 156 |
definition = function(object) {
|
|
| 157 | 2x |
apply(X = object, MARGIN = 2, FUN = univariate_ilr) |
| 158 |
} |
|
| 159 |
) |
| 1 |
# VARIANCE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Variance ===================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname variance |
|
| 8 |
#' @aliases variance,LogRatio-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "variance", |
|
| 11 |
signature = c("LogRatio"),
|
|
| 12 |
definition = function(x, row_weights = NULL, column_weights = TRUE) {
|
|
| 13 | 7x |
n <- nrow(x) |
| 14 | 7x |
m <- ncol(x) |
| 15 | ||
| 16 | 7x |
w_row <- rep(1 / n, n) |
| 17 | 7x |
if (length(row_weights) == n) {
|
| 18 | ! |
arkhe::assert_length(row_weights, n) |
| 19 | ! |
arkhe::assert_positive(row_weights, strict = FALSE) |
| 20 | ! |
w_row <- row_weights / sum(row_weights) # Sum up to 1 |
| 21 |
} |
|
| 22 | ||
| 23 | 7x |
w_col <- if (isTRUE(column_weights)) weights(x) else rep(1 / m, m) |
| 24 | 7x |
if (length(column_weights) == m) {
|
| 25 | ! |
arkhe::assert_length(column_weights, m) |
| 26 | ! |
arkhe::assert_positive(column_weights, strict = FALSE) |
| 27 | ! |
w_col <- column_weights / sum(column_weights) # Sum up to 1 |
| 28 |
} |
|
| 29 | ||
| 30 | 7x |
z <- sweep(x, MARGIN = 2, STATS = colSums(x * w_row), FUN = "-") |
| 31 | 7x |
z <- colSums(diag(w_row) %*% z^2 %*% diag(w_col)) |
| 32 | 7x |
names(z) <- colnames(x) |
| 33 | 7x |
z |
| 34 |
} |
|
| 35 |
) |
|
| 36 | ||
| 37 |
# Total variance =============================================================== |
|
| 38 |
#' @export |
|
| 39 |
#' @describeIn variance_total The total variance of compositional data is the |
|
| 40 |
#' trace of the [centred log-ratio covariance][covariance()] matrix |
|
| 41 |
#' (i.e. *totvar1* in Aitchison 1997). |
|
| 42 |
#' @aliases variance_total,CompositionMatrix-method |
|
| 43 |
setMethod( |
|
| 44 |
f = "variance_total", |
|
| 45 |
signature = c("CompositionMatrix"),
|
|
| 46 |
definition = function(x, sd = FALSE) {
|
|
| 47 | 3x |
z <- sum(diag(covariance(x, center = TRUE))) |
| 48 | 1x |
if (sd) z <- sqrt((1 / (ncol(x) - 1)) * z) |
| 49 | 3x |
z |
| 50 |
} |
|
| 51 |
) |
|
| 52 | ||
| 53 |
#' @export |
|
| 54 |
#' @describeIn variance_total Computes the total log-ratio variance. This is |
|
| 55 |
#' identical to the weighted sum-of-squared distances between samples |
|
| 56 |
#' (i.e. *totvar2* in Aitchison 1997). |
|
| 57 |
#' @aliases variance_total,LogRatio-method |
|
| 58 |
setMethod( |
|
| 59 |
f = "variance_total", |
|
| 60 |
signature = c("LogRatio"),
|
|
| 61 |
definition = function(x, row_weights = NULL, column_weights = TRUE) {
|
|
| 62 | 6x |
sum(variance(x, row_weights = row_weights, column_weights = column_weights)) |
| 63 |
} |
|
| 64 |
) |
|
| 65 |
| 1 |
# HELPERS |
|
| 2 | ||
| 3 |
## https://michaelchirico.github.io/potools/articles/developers.html |
|
| 4 |
tr_ <- function(...) {
|
|
| 5 | 11x |
enc2utf8(gettext(paste0(...), domain = "R-nexus")) |
| 6 |
} |
|
| 7 | ||
| 8 |
missingORnull <- function(x) {
|
|
| 9 | 4x |
missing(x) || is.null(x) |
| 10 |
} |
|
| 11 | ||
| 12 |
has_rownames <- function(x) {
|
|
| 13 | 45x |
.row_names_info(x, type = 1L) > 0L && |
| 14 | 45x |
!is.na(.row_names_info(x, type = 0L)[[1L]]) |
| 15 |
} |
|
| 16 | ||
| 17 |
make_names <- function(x, n = length(x), prefix = "X") {
|
|
| 18 | 90x |
x <- if (n > 0) x %||% paste0(prefix, seq_len(n)) else character(0) |
| 19 | 90x |
x <- make.unique(x, sep = "_") |
| 20 | 90x |
x |
| 21 |
} |
|
| 22 | ||
| 23 |
#' Plotting Dimensions of Character Strings |
|
| 24 |
#' |
|
| 25 |
#' Convert string length in inch to number of (margin) lines. |
|
| 26 |
#' @param x A [`character`] vector of string whose length is to be calculated. |
|
| 27 |
#' @param ... Further parameter to be passed to [graphics::strwidth()]`, such as |
|
| 28 |
#' `cex`. |
|
| 29 |
#' @return |
|
| 30 |
#' A [`numeric`] vector (maximum string width in units of margin lines). |
|
| 31 |
#' @note For internal use only. |
|
| 32 |
#' @family graphic tools |
|
| 33 |
#' @keywords internal |
|
| 34 |
#' @noRd |
|
| 35 |
width2line <- function(x, ...) {
|
|
| 36 | 4x |
(max(graphics::strwidth(x, units = "inch", ...)) / |
| 37 | 4x |
graphics::par("cin")[2] + graphics::par("mgp")[2]) * graphics::par("cex")
|
| 38 |
} |
|
| 39 |
height2line <- function(x, ...) {
|
|
| 40 | 4x |
(max(graphics::strheight(x, units = "inch", ...)) / |
| 41 | 4x |
graphics::par("cin")[2] + graphics::par("mgp")[2]) * graphics::par("cex")
|
| 42 |
} |
|
| 43 | ||
| 44 |
#' Label Percentages |
|
| 45 |
#' |
|
| 46 |
#' @param x A [`numeric`] vector. |
|
| 47 |
#' @param digits An [`integer`] indicating the number of decimal places. |
|
| 48 |
#' If `NULL` (the default), breaks will have the minimum number of digits |
|
| 49 |
#' needed to show the difference between adjacent values. |
|
| 50 |
#' @param trim A [`logical`] scalar. If `FALSE` (the default), values are |
|
| 51 |
#' right-justified to a common width (see [base::format()]). |
|
| 52 |
#' @return A [`character`] vector. |
|
| 53 |
#' @keywords internal |
|
| 54 |
#' @noRd |
|
| 55 |
label_percent <- function(x, digits = NULL, trim = FALSE) {
|
|
| 56 | 10x |
i <- !is.na(x) |
| 57 | 10x |
y <- x[i] |
| 58 | 10x |
y <- abs(y) * 100 |
| 59 | 10x |
y <- format(y, trim = trim, digits = digits) |
| 60 | 10x |
y <- paste0(y, "%") |
| 61 | 10x |
x[i] <- y |
| 62 | 10x |
x |
| 63 |
} |
|
| 64 | ||
| 65 |
#' Label Chemical Formula |
|
| 66 |
#' |
|
| 67 |
#' @param x A [`character`] vector. |
|
| 68 |
#' @return A [`character`] vector. |
|
| 69 |
#' @keywords internal |
|
| 70 |
#' @noRd |
|
| 71 |
label_chemical <- function(x, digits = NULL, trim = FALSE) {
|
|
| 72 | ! |
if (!all(is_chemical(x))) return(x) |
| 73 | 5x |
x <- gsub(pattern = "([[:digit:]]+)", replacement = "[\\1]", x = x, fixed = FALSE) |
| 74 | 5x |
x <- gsub(pattern = "([[:alpha:]]+)", replacement = "\"\\1\"", x = x, fixed = FALSE) |
| 75 | 5x |
gsub(pattern = "]\"", replacement = "]*\"", x = x, fixed = FALSE) |
| 76 |
} |
|
| 77 | ||
| 78 |
#' Column Weights |
|
| 79 |
#' |
|
| 80 |
#' Computes column weights. |
|
| 81 |
#' @param x A `numeric` [`matrix`]. |
|
| 82 |
#' @param weights A [`logical`] scalar: should varying weights (column means) |
|
| 83 |
#' be computed? If `FALSE` (the default), equally-weighted parts are used. |
|
| 84 |
#' Alternatively, a positive [`numeric`] vector of weights can be specified |
|
| 85 |
#' (will be rescaled to sum to \eqn{1}).
|
|
| 86 |
#' @return A [`numeric`] vector. |
|
| 87 |
#' @keywords internal |
|
| 88 |
#' @noRd |
|
| 89 |
make_weights <- function(x, weights = FALSE) {
|
|
| 90 | 32x |
D <- ncol(x) |
| 91 | ||
| 92 | 32x |
w <- if (isTRUE(weights)) colMeans(x) else rep(1 / D, D) |
| 93 | 32x |
if (is.numeric(weights)) {
|
| 94 | 3x |
arkhe::assert_length(weights, D) |
| 95 | 3x |
arkhe::assert_positive(weights, strict = TRUE) |
| 96 | 3x |
w <- weights / sum(weights) # Sum up to 1 |
| 97 |
} |
|
| 98 | ||
| 99 | 32x |
unname(w) |
| 100 |
} |
| 1 |
# BARPLOT |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# CompositionMatrix ============================================================ |
|
| 6 |
#' @export |
|
| 7 |
#' @method barplot CompositionMatrix |
|
| 8 |
barplot.CompositionMatrix <- function(height, ..., |
|
| 9 |
order_columns = FALSE, order_rows = NULL, |
|
| 10 |
decreasing = TRUE, names = TRUE, |
|
| 11 |
space = 0.2, offset = 0.025, |
|
| 12 |
color = NULL, border = NA, |
|
| 13 |
axes = TRUE, legend = TRUE) {
|
|
| 14 |
## Validation |
|
| 15 | 4x |
if (ncol(height) < 2) {
|
| 16 | ! |
stop(tr_("At least two compositional parts are needed."), call. = FALSE)
|
| 17 |
} |
|
| 18 | ||
| 19 |
## Prepare data |
|
| 20 | 4x |
xy <- prepare_barplot(height, order_columns = order_columns, |
| 21 | 4x |
order_rows = order_rows, decreasing = decreasing, |
| 22 | 4x |
offset = offset) |
| 23 | 4x |
parts <- factor(xy$data$column, levels = colnames(height)) |
| 24 | 4x |
col <- khroma::palette_color_discrete(color)(parts) |
| 25 | 4x |
n <- nrow(height) |
| 26 | ||
| 27 |
## Graphical parameters |
|
| 28 | 4x |
cex.axis <- list(...)$cex.axis %||% graphics::par("cex.axis")
|
| 29 | 4x |
col.axis <- list(...)$col.axis %||% graphics::par("col.axis")
|
| 30 | 4x |
font.axis <- list(...)$font.axis %||% graphics::par("font.axis")
|
| 31 | ||
| 32 |
## Save and restore |
|
| 33 | 4x |
mar <- graphics::par("mar")
|
| 34 | 4x |
nlines <- height2line("M", cex = cex.axis)
|
| 35 | 4x |
mar[1] <- 3 |
| 36 | 4x |
mar[2] <- if (names) width2line(rownames(height), cex = cex.axis) + 0.1 else nlines |
| 37 | 4x |
mar[3] <- nlines |
| 38 | 4x |
mar[4] <- nlines |
| 39 | ||
| 40 | 4x |
old_par <- graphics::par(mar = mar) |
| 41 | 4x |
on.exit(graphics::par(old_par), add = TRUE) |
| 42 | ||
| 43 |
## Open new window |
|
| 44 | 4x |
grDevices::dev.hold() |
| 45 | 4x |
on.exit(grDevices::dev.flush(), add = TRUE) |
| 46 | 4x |
graphics::plot.new() |
| 47 | ||
| 48 |
## Set plotting coordinates |
|
| 49 | 4x |
space <- 1 / n * 0.5 - space / n * 0.5 |
| 50 | 4x |
xlim <- range(0, 1) |
| 51 | 4x |
ylim <- range(xy$data$y) |
| 52 | 4x |
ylim <- ylim + c(0, 2 * (offset + space) * legend) + c(-1, 1) * space |
| 53 | 4x |
graphics::plot.window(xlim = xlim, ylim = ylim, xaxs = "i", yaxs = "i") |
| 54 | ||
| 55 |
## Plot |
|
| 56 | 4x |
graphics::rect( |
| 57 | 4x |
xleft = xy$data$xmin, |
| 58 | 4x |
ybottom = xy$data$y - space, |
| 59 | 4x |
xright = xy$data$xmax, |
| 60 | 4x |
ytop = xy$data$y + space, |
| 61 | 4x |
col = col, |
| 62 | 4x |
border = border |
| 63 |
) |
|
| 64 | ||
| 65 |
## Construct axis |
|
| 66 | 4x |
if (axes) {
|
| 67 | 4x |
at <- graphics::axTicks(side = 1) |
| 68 | 4x |
graphics::axis(side = 1, at = at, labels = label_percent(at), |
| 69 | 4x |
xpd = NA, las = 1, cex.axis = cex.axis, col.axis = col.axis, |
| 70 | 4x |
font.axis = font.axis) |
| 71 | 4x |
graphics::mtext(text = names(xy$groups), side = 4, line = 0, at = xy$groups, |
| 72 | 4x |
cex = cex.axis, col = col.axis, font = font.axis) |
| 73 | 4x |
if (names) {
|
| 74 | 4x |
graphics::axis(side = 2, at = unique(xy$data$y), labels = unique(xy$data$row), |
| 75 | 4x |
las = 2, lty = 0, cex.axis = cex.axis, col.axis = col.axis, |
| 76 | 4x |
font.axis = font.axis) |
| 77 |
} |
|
| 78 |
} |
|
| 79 | ||
| 80 |
## Add legend |
|
| 81 | 4x |
if (legend) {
|
| 82 | 4x |
graphics::rect( |
| 83 | 4x |
xleft = cumsum(xy$mean) - xy$mean, |
| 84 | 4x |
ybottom = max(xy$data$y) + offset + space, |
| 85 | 4x |
xright = cumsum(xy$mean), |
| 86 | 4x |
ytop = max(xy$data$y) + 2 * (offset + space), |
| 87 | 4x |
col = unique(col), |
| 88 | 4x |
border = border |
| 89 |
) |
|
| 90 | 4x |
lab <- label_chemical(names(xy$mean)) |
| 91 | 4x |
graphics::mtext(text = parse(text = lab), side = 3, line = 0, |
| 92 | 4x |
at = cumsum(xy$mean) - xy$mean / 2, |
| 93 | 4x |
cex = cex.axis, col = unique(col), font = font.axis) |
| 94 |
} |
|
| 95 | ||
| 96 | 4x |
invisible(height) |
| 97 |
} |
|
| 98 | ||
| 99 |
#' @export |
|
| 100 |
#' @rdname barplot |
|
| 101 |
#' @aliases barplot,CompositionMatrix-method |
|
| 102 |
setMethod("barplot", c(height = "CompositionMatrix"), barplot.CompositionMatrix)
|
|
| 103 | ||
| 104 |
prepare_barplot <- function(x, order_rows = NULL, order_columns = FALSE, |
|
| 105 |
decreasing = TRUE, offset = 0.025, |
|
| 106 |
verbose = getOption("nexus.verbose")) {
|
|
| 107 |
## Remove missing values |
|
| 108 | 4x |
x <- arkhe::remove_NA(x, margin = 2, verbose = verbose) |
| 109 | ||
| 110 |
## Relative frequencies |
|
| 111 | 4x |
n <- nrow(x) |
| 112 | 4x |
x <- x / rowSums(x) |
| 113 | ||
| 114 |
## Validation |
|
| 115 | 4x |
stopifnot(is_composition(x)) |
| 116 | ||
| 117 |
## Row order |
|
| 118 | 4x |
if (!is.null(order_rows)) {
|
| 119 | 1x |
j <- x[, order_rows, drop = TRUE] |
| 120 | 1x |
i <- order(j, decreasing = decreasing) |
| 121 | 1x |
x <- x[i, , drop = FALSE] |
| 122 |
} |
|
| 123 | ||
| 124 |
## Columns order |
|
| 125 | 4x |
center <- mean(x) |
| 126 | 4x |
if (order_columns) {
|
| 127 | 2x |
col_order <- order(center, decreasing = FALSE) |
| 128 | 2x |
center <- center[col_order] |
| 129 | 2x |
x <- x[, col_order, drop = FALSE] |
| 130 |
} |
|
| 131 | ||
| 132 |
## Grouping |
|
| 133 | 4x |
if (!is_grouped(x)) {
|
| 134 | 3x |
x <- group(x, by = rep(NA, n), verbose = FALSE) |
| 135 |
} |
|
| 136 | 4x |
spl <- group_split(x) |
| 137 | 4x |
z <- do.call(rbind, spl) |
| 138 | ||
| 139 |
## Build a long table |
|
| 140 | 4x |
row <- row(z, as.factor = TRUE) |
| 141 | 4x |
col <- col(z, as.factor = TRUE) |
| 142 | 4x |
data <- data.frame( |
| 143 | 4x |
row = as.vector(row), |
| 144 | 4x |
column = as.vector(col), |
| 145 | 4x |
value = as.vector(z) |
| 146 |
) |
|
| 147 | ||
| 148 | 4x |
xmax <- t(apply(X = z, MARGIN = 1, FUN = cumsum)) |
| 149 | 4x |
xmin <- xmax - z |
| 150 | 4x |
data$xmin <- as.vector(xmin) |
| 151 | 4x |
data$xmax <- as.vector(xmax) |
| 152 | 4x |
data$y <- as.vector(n + 1 - as.numeric(row)) / n # Reverse levels order |
| 153 | ||
| 154 |
## Offset |
|
| 155 | 4x |
n_grp <- group_n(x) |
| 156 | 4x |
n_spl <- group_size(x) |
| 157 | 4x |
offset <- rev(seq_len(n_grp)) * offset - offset |
| 158 | 4x |
data$y <- data$y + rep(offset, n_spl)[as.numeric(row)] |
| 159 | ||
| 160 | 4x |
list( |
| 161 | 4x |
data = data, |
| 162 | 4x |
mean = center, |
| 163 | 4x |
groups = 1 - cumsum(n_spl) / n + n_spl / n * 0.5 + offset |
| 164 |
) |
|
| 165 |
} |
| 1 |
# ACCESSORS |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Extract ====================================================================== |
|
| 6 |
.subscript1 <- function(x, i) {
|
|
| 7 | 5x |
x@.Data[i] |
| 8 |
} |
|
| 9 | ||
| 10 |
.subscript2 <- function(x, i, j, drop) {
|
|
| 11 |
## Rows |
|
| 12 | 184x |
if (missing(i)) i <- seq_len(nrow(x)) |
| 13 | ! |
if (is.character(i)) i <- match(i, dimnames(x)[1L]) |
| 14 | 848x |
totals <- totals(x)[i] |
| 15 | ||
| 16 |
## Columns |
|
| 17 | 658x |
if (missing(j)) j <- seq_len(ncol(x)) |
| 18 | ||
| 19 |
## Subset |
|
| 20 | 848x |
z <- x@.Data[i, j, drop = drop] |
| 21 | 727x |
if (drop) return(z) |
| 22 | ||
| 23 |
## /!\ Subcomposition /!\ |
|
| 24 |
# if (ncol(z) < ncol(x)) {
|
|
| 25 |
# tot <- rowSums(z, na.rm = TRUE) |
|
| 26 |
# totals <- totals * tot |
|
| 27 |
# z <- z / tot |
|
| 28 |
# } |
|
| 29 | ||
| 30 | 121x |
if (is_grouped(x)) {
|
| 31 | 67x |
g <- droplevels(group_factor(x, exclude = NULL)[i]) |
| 32 | 67x |
methods::initialize( |
| 33 | 67x |
x, z, |
| 34 | 67x |
totals = totals, |
| 35 | 67x |
group_indices = as.integer(g), |
| 36 | 67x |
group_levels = levels(g), |
| 37 | 67x |
group_ordered = is.ordered(g) |
| 38 |
) |
|
| 39 |
} else {
|
|
| 40 | 54x |
methods::initialize(x, z, totals = totals) |
| 41 |
} |
|
| 42 |
} |
|
| 43 | ||
| 44 |
wrong_dimensions <- function(i, j) {
|
|
| 45 | 7x |
msg <- sprintf("M[%s%s]: incorrect number of dimensions.", i, j)
|
| 46 | 7x |
stop(msg, call. = FALSE) |
| 47 |
} |
|
| 48 | ||
| 49 |
## CompositionMatrix ----------------------------------------------------------- |
|
| 50 |
#' @export |
|
| 51 |
#' @rdname subset |
|
| 52 |
#' @aliases [,CompositionMatrix,missing,missing,missing-method |
|
| 53 |
setMethod( |
|
| 54 |
f = "[", |
|
| 55 |
signature = c(x = "CompositionMatrix", i = "missing", j = "missing", drop = "missing"), |
|
| 56 |
definition = function(x, i, j, ..., drop) {
|
|
| 57 | 5x |
na <- nargs() |
| 58 | 2x |
if (na == 2L) return(x) # x[] |
| 59 | 2x |
if (na == 3L) return(x) # x[, ] |
| 60 | 1x |
wrong_dimensions(".", ".") # x[, , ], etc.
|
| 61 |
} |
|
| 62 |
) |
|
| 63 | ||
| 64 |
#' @export |
|
| 65 |
#' @rdname subset |
|
| 66 |
#' @aliases [,CompositionMatrix,missing,missing,logical-method |
|
| 67 |
setMethod( |
|
| 68 |
f = "[", |
|
| 69 |
signature = c(x = "CompositionMatrix", i = "missing", j = "missing", drop = "logical"), |
|
| 70 |
definition = function(x, i, j, ..., drop) {
|
|
| 71 | ! |
na <- nargs() |
| 72 | ! |
if (na < 4L) return(x) # x[drop=], x[, drop=], x[drop=, ] |
| 73 | ! |
if (na == 4L) {
|
| 74 | ! |
x <- if (drop) x@.Data else x |
| 75 | ! |
return(x) # x[, , drop=], x[, drop=, ], x[drop=, , ] |
| 76 |
} |
|
| 77 | ! |
wrong_dimensions(".", ".") # x[, , , drop=], etc.
|
| 78 |
} |
|
| 79 |
) |
|
| 80 | ||
| 81 |
#' @export |
|
| 82 |
#' @rdname subset |
|
| 83 |
#' @aliases [,CompositionMatrix,index,missing,missing-method |
|
| 84 |
setMethod( |
|
| 85 |
f = "[", |
|
| 86 |
signature = c(x = "CompositionMatrix", i = "index", j = "missing", drop = "missing"), |
|
| 87 |
definition = function(x, i, j, ..., drop) {
|
|
| 88 | 4x |
na <- nargs() |
| 89 | 4x |
if (na == 2L) {
|
| 90 | 2x |
x <- .subscript1(x, i) |
| 91 | 2x |
return(x) # x[i=] |
| 92 |
} |
|
| 93 | 2x |
if (na == 3L) {
|
| 94 |
#/!\ DROP /!\ |
|
| 95 | 1x |
x <- .subscript2(x, i, , drop = FALSE) |
| 96 | 1x |
return(x) # x[i=, ], x[, i=] |
| 97 |
} |
|
| 98 | 1x |
wrong_dimensions("i", ".") # x[i=, , ], etc.
|
| 99 |
} |
|
| 100 |
) |
|
| 101 | ||
| 102 |
#' @export |
|
| 103 |
#' @rdname subset |
|
| 104 |
#' @aliases [,CompositionMatrix,index,missing,logical-method |
|
| 105 |
setMethod( |
|
| 106 |
f = "[", |
|
| 107 |
signature = c(x = "CompositionMatrix", i = "index", j = "missing", drop = "logical"), |
|
| 108 |
definition = function(x, i, j, ..., drop) {
|
|
| 109 | 659x |
na <- nargs() |
| 110 | 659x |
if (na == 3L) {
|
| 111 | 1x |
x <- .subscript1(x, i) |
| 112 | 1x |
return(x) # x[i=, drop=] |
| 113 |
} |
|
| 114 | 658x |
if (na == 4L) {
|
| 115 | 657x |
x <- .subscript2(x, i, , drop = drop) |
| 116 | 657x |
return(x) # x[i=, , drop=], x[, i=, drop=] |
| 117 |
} |
|
| 118 | 1x |
wrong_dimensions("i", ".") # x[i=, , , drop=], etc.
|
| 119 |
} |
|
| 120 |
) |
|
| 121 | ||
| 122 |
#' @export |
|
| 123 |
#' @rdname subset |
|
| 124 |
#' @aliases [,CompositionMatrix,missing,index,missing-method |
|
| 125 |
setMethod( |
|
| 126 |
f = "[", |
|
| 127 |
signature = c(x = "CompositionMatrix", i = "missing", j = "index", drop = "missing"), |
|
| 128 |
definition = function(x, i, j, ..., drop) {
|
|
| 129 | 23x |
na <- nargs() |
| 130 | 23x |
if (na == 2L) {
|
| 131 | 1x |
x <- .subscript1(x, j) # x[j=] |
| 132 | 1x |
return(x) |
| 133 |
} |
|
| 134 | 22x |
if (na == 3L) {
|
| 135 |
# /!\ DROP /!\ |
|
| 136 | 21x |
x <- .subscript2(x, , j, drop = FALSE) # x[j=, ], x[, j=] |
| 137 | 21x |
return(x) |
| 138 |
} |
|
| 139 | 1x |
wrong_dimensions(".", "j") # x[, j=, ], etc.
|
| 140 |
} |
|
| 141 |
) |
|
| 142 | ||
| 143 |
#' @export |
|
| 144 |
#' @rdname subset |
|
| 145 |
#' @aliases [,CompositionMatrix,missing,index,logical-method |
|
| 146 |
setMethod( |
|
| 147 |
f = "[", |
|
| 148 |
signature = c(x = "CompositionMatrix", i = "missing", j = "index", drop = "logical"), |
|
| 149 |
definition = function(x, i, j, ..., drop) {
|
|
| 150 | 165x |
na <- nargs() |
| 151 | 165x |
if (na == 3L) {
|
| 152 | 1x |
x <- .subscript1(x, j) # x[j=, drop=] |
| 153 | 1x |
return(x) |
| 154 |
} |
|
| 155 | 164x |
if (na == 4L) {
|
| 156 | 163x |
x <- .subscript2(x, , j, drop = drop) # x[j=, , drop=], x[, j=, drop=] |
| 157 | 163x |
return(x) |
| 158 |
} |
|
| 159 | 1x |
wrong_dimensions(".", "j") # x[, j=, , drop=], etc.
|
| 160 |
} |
|
| 161 |
) |
|
| 162 | ||
| 163 |
#' @export |
|
| 164 |
#' @rdname subset |
|
| 165 |
#' @aliases [,CompositionMatrix,index,index,missing-method |
|
| 166 |
setMethod( |
|
| 167 |
f = "[", |
|
| 168 |
signature = c(x = "CompositionMatrix", i = "index", j = "index", drop = "missing"), |
|
| 169 |
definition = function(x, i, j, ..., drop) {
|
|
| 170 | 2x |
na <- nargs() |
| 171 | 2x |
if (na == 3L) {
|
| 172 |
# /!\ DROP /!\ |
|
| 173 | 1x |
x <- .subscript2(x, i, j, drop = FALSE) # x[i=, j=], x[j=, i=] |
| 174 | 1x |
return(x) |
| 175 |
} |
|
| 176 | 1x |
wrong_dimensions("i", "j") # x[i=, j=, ], etc.
|
| 177 |
} |
|
| 178 |
) |
|
| 179 | ||
| 180 |
#' @export |
|
| 181 |
#' @rdname subset |
|
| 182 |
#' @aliases [,CompositionMatrix,index,index,logical-method |
|
| 183 |
setMethod( |
|
| 184 |
f = "[", |
|
| 185 |
signature = c(x = "CompositionMatrix", i = "index", j = "index", drop = "logical"), |
|
| 186 |
definition = function(x, i, j, ..., drop) {
|
|
| 187 | 6x |
na <- nargs() |
| 188 | 6x |
if (na == 4L) {
|
| 189 | 5x |
x <- .subscript2(x, i, j, drop = drop) # x[i=, j=, drop=], x[j=, i=, drop=] |
| 190 | 5x |
return(x) |
| 191 |
} |
|
| 192 | 1x |
wrong_dimensions("i", "j") # x[i=, j=, , drop=], etc.
|
| 193 |
} |
|
| 194 |
) |
|
| 195 | ||
| 196 |
# Replace ====================================================================== |
|
| 197 |
## [<- ------------------------------------------------------------------------- |
|
| 198 |
#' @export |
|
| 199 |
#' @rdname subset |
|
| 200 |
#' @aliases [<-,CompositionMatrix-method |
|
| 201 |
setMethod( |
|
| 202 |
f = "[<-", |
|
| 203 |
signature = c(x = "CompositionMatrix"), |
|
| 204 |
function(x, i, j, ..., value) {
|
|
| 205 | 5x |
z <- methods::callNextMethod() |
| 206 | 5x |
methods::validObject(z) |
| 207 | 5x |
z |
| 208 |
} |
|
| 209 |
) |
|
| 210 | ||
| 211 |
## [[<- ------------------------------------------------------------------------ |
|
| 212 |
#' @export |
|
| 213 |
#' @rdname subset |
|
| 214 |
#' @aliases [[<-,CompositionMatrix-method |
|
| 215 |
setMethod( |
|
| 216 |
f = "[[<-", |
|
| 217 |
signature = c(x = "CompositionMatrix"), |
|
| 218 |
function(x, i, j, ..., value) {
|
|
| 219 | 2x |
z <- methods::callNextMethod() |
| 220 | 2x |
methods::validObject(z) |
| 221 | 2x |
z |
| 222 |
} |
|
| 223 |
) |
|
| 224 | ||
| 225 |
# Transpose ==================================================================== |
|
| 226 |
#' @export |
|
| 227 |
#' @rdname t |
|
| 228 |
#' @aliases t,CompositionMatrix-method |
|
| 229 |
setMethod( |
|
| 230 |
f = "t", |
|
| 231 |
signature = c(x = "CompositionMatrix"), |
|
| 232 |
function(x) {
|
|
| 233 | 1x |
t(x@.Data) |
| 234 |
} |
|
| 235 |
) |
|
| 236 | ||
| 237 |
#' @export |
|
| 238 |
#' @rdname t |
|
| 239 |
#' @aliases t,LogRatio-method |
|
| 240 |
setMethod( |
|
| 241 |
f = "t", |
|
| 242 |
signature = c(x = "LogRatio"), |
|
| 243 |
function(x) {
|
|
| 244 | 1x |
t(x@.Data) |
| 245 |
} |
|
| 246 |
) |
| 1 |
# REPLACE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Zeros ======================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname replace_zero |
|
| 8 |
#' @aliases replace_zero,CompositionMatrix-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "replace_zero", |
|
| 11 |
signature = c(x = "CompositionMatrix"), |
|
| 12 |
definition = function(x, value, delta = 2/3) {
|
|
| 13 |
## Validation |
|
| 14 | 1x |
D <- ncol(x) |
| 15 | ! |
if (is.null(value)) return(x) |
| 16 | ! |
if (length(value) == 1) value <- rep(value, D) |
| 17 | 1x |
if (length(value) > 1) arkhe::assert_length(value, D) |
| 18 | ! |
if (length(delta) > 1) arkhe::assert_length(delta, D) |
| 19 | ||
| 20 | 1x |
sigma <- value * delta |
| 21 | 1x |
r <- apply(X = x, MARGIN = 1, FUN = zero_multiplicative, sigma = sigma) |
| 22 | ||
| 23 | 1x |
methods::initialize(x, t(r)) |
| 24 |
} |
|
| 25 |
) |
|
| 26 | ||
| 27 |
# zero_additive <- function(x, sigma) {
|
|
| 28 |
# D <- length(x) |
|
| 29 |
# |
|
| 30 |
# is_zero <- x == 0 |
|
| 31 |
# Z <- sum(is_zero) |
|
| 32 |
# |
|
| 33 |
# x[is_zero] <- (sigma * (Z + 1) * (D - Z)) / D^2 |
|
| 34 |
# x[!is_zero] <- x[!is_zero] - (sigma * (Z + 1) * Z) / D^2 |
|
| 35 |
# |
|
| 36 |
# x |
|
| 37 |
# } |
|
| 38 |
zero_multiplicative <- function(x, sigma) {
|
|
| 39 | 9x |
is_zero <- x == 0 & !is.na(x) |
| 40 | 9x |
x[is_zero] <- sigma[is_zero] |
| 41 | 9x |
x[!is_zero] <- x[!is_zero] * (1 - sum(sigma[is_zero]) / 1) |
| 42 | 9x |
x |
| 43 |
} |
|
| 44 | ||
| 45 |
# Missing values =============================================================== |
|
| 46 |
#' @export |
|
| 47 |
#' @rdname replace_NA |
|
| 48 |
#' @aliases replace_NA,CompositionMatrix-method |
|
| 49 |
setMethod( |
|
| 50 |
f = "replace_NA", |
|
| 51 |
signature = c(x = "CompositionMatrix"), |
|
| 52 |
definition = function(x, value) {
|
|
| 53 |
## Validation |
|
| 54 | 2x |
D <- ncol(x) |
| 55 | ! |
if (is.null(value)) return(x) |
| 56 | 2x |
if (length(value) == 1) value <- rep(value, D) |
| 57 | 2x |
if (length(value) > 1) arkhe::assert_length(value, D) |
| 58 | ||
| 59 | 2x |
r <- apply(X = x, MARGIN = 1, FUN = missing_multiplicative, sigma = value) |
| 60 | ||
| 61 | 2x |
methods::initialize(x, t(r)) |
| 62 |
} |
|
| 63 |
) |
|
| 64 | ||
| 65 |
missing_multiplicative <- function(x, sigma) {
|
|
| 66 | 18x |
is_missing <- is.na(x) |
| 67 | 18x |
x[is_missing] <- sigma[is_missing] |
| 68 | 18x |
x[!is_missing] <- x[!is_missing] * (1 - sum(sigma[is_missing])) / sum(x[!is_missing]) |
| 69 | 18x |
x |
| 70 |
} |
| 1 |
# GROUPS |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
.group_extract <- function(object, which) {
|
|
| 6 |
## Validation |
|
| 7 | 1x |
arkhe::assert_type(which, "character") |
| 8 | ! |
if (!any_assigned(object)) stop("No group is defined.", call. = FALSE)
|
| 9 | ||
| 10 | 1x |
ok <- group_names(object) %in% which |
| 11 | 1x |
if (!any(ok)) {
|
| 12 | ! |
msg <- ngettext(length(which), "No sample belongs to the group: %s.", |
| 13 | ! |
"No sample belongs to the groups: %s.") |
| 14 | ! |
message(sprintf(msg, paste0(dQuote(which), collapse = ", "))) |
| 15 | ! |
return(object) |
| 16 |
} |
|
| 17 | ||
| 18 | 1x |
object[ok, , drop = FALSE] |
| 19 |
} |
|
| 20 | ||
| 21 |
#' @export |
|
| 22 |
#' @rdname group_subset |
|
| 23 |
#' @aliases group_subset,GroupedComposition-method |
|
| 24 |
setMethod( |
|
| 25 |
f = "group_subset", |
|
| 26 |
signature = c("GroupedComposition"),
|
|
| 27 |
definition = .group_extract |
|
| 28 |
) |
|
| 29 | ||
| 30 |
#' @export |
|
| 31 |
#' @rdname group_subset |
|
| 32 |
#' @aliases group_subset,GroupedLogRatio-method |
|
| 33 |
setMethod( |
|
| 34 |
f = "group_subset", |
|
| 35 |
signature = c("GroupedLogRatio"),
|
|
| 36 |
definition = .group_extract |
|
| 37 |
) |
|
| 38 | ||
| 39 |
# Groups ======================================================================= |
|
| 40 |
#' Compute Groups |
|
| 41 |
#' |
|
| 42 |
#' @param x A ([`list`] of) [`factor`]s for which interaction is to be computed. |
|
| 43 |
#' @param drop_levels A [`logical`] scalar: should unused factor levels be |
|
| 44 |
#' dropped? |
|
| 45 |
#' @param allow_na A [`logical`] scalar: should `NA` be considered an extra |
|
| 46 |
#' level? |
|
| 47 |
#' @return A [`factor`] vector. |
|
| 48 |
#' @keywords internal |
|
| 49 |
#' @noRd |
|
| 50 |
compute_groups <- function(x, drop_levels = TRUE, allow_na = TRUE) {
|
|
| 51 | 22x |
if (is.list(x)) {
|
| 52 | 2x |
x <- if (length(x) > 1) interaction(x, sep = "_") else x[[1L]] |
| 53 |
} |
|
| 54 | 22x |
x <- as.factor(x) |
| 55 | 22x |
if (drop_levels) x <- droplevels(x) |
| 56 | 22x |
if (allow_na) x <- addNA(x, ifany = TRUE) |
| 57 | ||
| 58 | 22x |
x |
| 59 |
} |
|
| 60 | ||
| 61 |
#' Validate Groups |
|
| 62 |
#' |
|
| 63 |
#' @param object A [`matrix`]-like object. |
|
| 64 |
#' @param by A ([`list`] of) [`factor`]s for which interaction is to be computed. |
|
| 65 |
#' @param verbose A [`logical`] scalar: should \R report extra information |
|
| 66 |
#' on progress? |
|
| 67 |
#' @return Invisibly returns `by`. |
|
| 68 |
#' @keywords internal |
|
| 69 |
#' @noRd |
|
| 70 |
validate_groups <- function(object, by, verbose = getOption("nexus.verbose")) {
|
|
| 71 | 22x |
arkhe::assert_type(by, "integer") |
| 72 | 22x |
arkhe::assert_length(by, nrow(object)) |
| 73 | ||
| 74 | 21x |
if (nlevels(by) == 0) {
|
| 75 | ! |
stop(tr_("Nothing to group by."), call. = FALSE)
|
| 76 |
} |
|
| 77 | 21x |
if (isTRUE(verbose)) {
|
| 78 | 1x |
if (nlevels(by) == nrow(object)) {
|
| 79 | ! |
message(tr_("As many groups as individuals."))
|
| 80 |
} |
|
| 81 | ||
| 82 | 1x |
n <- nlevels(by) |
| 83 | 1x |
what <- ngettext(n, "Found %g group (%s)", "Found %g groups (%s)") |
| 84 | 1x |
grp <- paste0(levels(by), collapse = ", ") |
| 85 | 1x |
message(sprintf(what, n, grp)) |
| 86 |
} |
|
| 87 | ||
| 88 | 21x |
invisible(by) |
| 89 |
} |
|
| 90 | ||
| 91 |
#' @export |
|
| 92 |
#' @rdname group |
|
| 93 |
#' @aliases group,CompositionMatrix-method |
|
| 94 |
setMethod( |
|
| 95 |
f = "group", |
|
| 96 |
signature = "CompositionMatrix", |
|
| 97 |
definition = function(object, by, verbose = getOption("nexus.verbose"), ...) {
|
|
| 98 |
## Compute groups |
|
| 99 | 22x |
by <- compute_groups(by, ...) |
| 100 | ||
| 101 |
## Validation |
|
| 102 | 22x |
validate_groups(object, by, verbose = verbose) |
| 103 | ||
| 104 | 21x |
.GroupedComposition( |
| 105 | 21x |
object, |
| 106 | 21x |
group_indices = as.integer(by), |
| 107 | 21x |
group_levels = levels(by), |
| 108 | 21x |
group_ordered = is.ordered(by) |
| 109 |
) |
|
| 110 |
} |
|
| 111 |
) |
|
| 112 | ||
| 113 |
#' @export |
|
| 114 |
#' @rdname group |
|
| 115 |
#' @aliases group,GroupedComposition-method |
|
| 116 |
setMethod( |
|
| 117 |
f = "group", |
|
| 118 |
signature = "GroupedComposition", |
|
| 119 |
definition = function(object, by, add = FALSE, |
|
| 120 |
verbose = getOption("nexus.verbose"), ...) {
|
|
| 121 |
## Compute groups |
|
| 122 | 4x |
if (isTRUE(add)) {
|
| 123 | 1x |
if (!is.list(by)) by <- list(by) |
| 124 | 1x |
by <- c(list(group_factor(object, exclude = NULL)), by) |
| 125 |
} |
|
| 126 | 4x |
methods::callNextMethod(object, by = by, verbose = verbose, ...) |
| 127 |
} |
|
| 128 |
) |
|
| 129 | ||
| 130 |
#' @export |
|
| 131 |
#' @rdname group |
|
| 132 |
#' @aliases ungroup,GroupedComposition-method |
|
| 133 |
setMethod( |
|
| 134 |
f = "ungroup", |
|
| 135 |
signature = "GroupedComposition", |
|
| 136 |
definition = function(object) {
|
|
| 137 | 21x |
methods::as(object, "CompositionMatrix", strict = TRUE) |
| 138 |
} |
|
| 139 |
) |
|
| 140 | ||
| 141 |
#' @export |
|
| 142 |
#' @rdname group |
|
| 143 |
#' @aliases ungroup,GroupedLR-method |
|
| 144 |
setMethod( |
|
| 145 |
f = "ungroup", |
|
| 146 |
signature = "GroupedLR", |
|
| 147 |
definition = function(object) {
|
|
| 148 | ! |
methods::as(object, "LR", strict = TRUE) |
| 149 |
} |
|
| 150 |
) |
|
| 151 | ||
| 152 |
#' @export |
|
| 153 |
#' @rdname group |
|
| 154 |
#' @aliases ungroup,GroupedCLR-method |
|
| 155 |
setMethod( |
|
| 156 |
f = "ungroup", |
|
| 157 |
signature = "GroupedCLR", |
|
| 158 |
definition = function(object) {
|
|
| 159 | ! |
methods::as(object, "CLR", strict = TRUE) |
| 160 |
} |
|
| 161 |
) |
|
| 162 | ||
| 163 |
#' @export |
|
| 164 |
#' @rdname group |
|
| 165 |
#' @aliases ungroup,GroupedALR-method |
|
| 166 |
setMethod( |
|
| 167 |
f = "ungroup", |
|
| 168 |
signature = "GroupedALR", |
|
| 169 |
definition = function(object) {
|
|
| 170 | ! |
methods::as(object, "ALR", strict = TRUE) |
| 171 |
} |
|
| 172 |
) |
|
| 173 | ||
| 174 |
#' @export |
|
| 175 |
#' @rdname group |
|
| 176 |
#' @aliases ungroup,GroupedILR-method |
|
| 177 |
setMethod( |
|
| 178 |
f = "ungroup", |
|
| 179 |
signature = "GroupedILR", |
|
| 180 |
definition = function(object) {
|
|
| 181 | 1x |
methods::as(object, "ILR", strict = TRUE) |
| 182 |
} |
|
| 183 |
) |
|
| 184 | ||
| 185 |
#' @export |
|
| 186 |
#' @rdname group |
|
| 187 |
#' @aliases ungroup,GroupedPLR-method |
|
| 188 |
setMethod( |
|
| 189 |
f = "ungroup", |
|
| 190 |
signature = "GroupedPLR", |
|
| 191 |
definition = function(object) {
|
|
| 192 | ! |
methods::as(object, "PLR", strict = TRUE) |
| 193 |
} |
|
| 194 |
) |
|
| 195 | ||
| 196 |
# Metadata ===================================================================== |
|
| 197 |
#' @export |
|
| 198 |
#' @rdname group_names |
|
| 199 |
#' @aliases group_levels,ReferenceGroups-method |
|
| 200 |
setMethod( |
|
| 201 |
f = "group_levels", |
|
| 202 |
signature = "ReferenceGroups", |
|
| 203 | 234x |
definition = function(object) object@group_levels |
| 204 |
) |
|
| 205 | ||
| 206 |
#' @export |
|
| 207 |
#' @rdname group_names |
|
| 208 |
#' @aliases group_names,ReferenceGroups-method |
|
| 209 |
setMethod( |
|
| 210 |
f = "group_names", |
|
| 211 |
signature = "ReferenceGroups", |
|
| 212 | 115x |
definition = function(object) group_levels(object)[group_indices(object)] |
| 213 |
) |
|
| 214 | ||
| 215 |
is_ordered <- function(object) {
|
|
| 216 | 102x |
isTRUE(object@group_ordered) |
| 217 |
} |
|
| 218 | ||
| 219 |
#' @export |
|
| 220 |
#' @rdname group_names |
|
| 221 |
#' @aliases group_factor,ReferenceGroups-method |
|
| 222 |
setMethod( |
|
| 223 |
f = "group_factor", |
|
| 224 |
signature = "ReferenceGroups", |
|
| 225 |
definition = function(object, exclude = NA) {
|
|
| 226 | 101x |
factor( |
| 227 | 101x |
x = group_names(object), |
| 228 | 101x |
levels = group_levels(object), |
| 229 | 101x |
exclude = exclude, |
| 230 | 101x |
ordered = is_ordered(object) |
| 231 |
) |
|
| 232 |
} |
|
| 233 |
) |
|
| 234 | ||
| 235 |
#' @export |
|
| 236 |
#' @rdname group_names |
|
| 237 |
#' @aliases group_indices,ReferenceGroups-method |
|
| 238 |
setMethod( |
|
| 239 |
f = "group_indices", |
|
| 240 |
signature = "ReferenceGroups", |
|
| 241 | 117x |
definition = function(object) object@group_indices |
| 242 |
) |
|
| 243 | ||
| 244 |
#' @export |
|
| 245 |
#' @rdname group_names |
|
| 246 |
#' @aliases group_rows,ReferenceGroups-method |
|
| 247 |
setMethod( |
|
| 248 |
f = "group_rows", |
|
| 249 |
signature = "ReferenceGroups", |
|
| 250 |
definition = function(object) {
|
|
| 251 | 18x |
i <- group_factor(object, exclude = NULL) |
| 252 | 18x |
split(seq_along(i), f = i) |
| 253 |
} |
|
| 254 |
) |
|
| 255 | ||
| 256 |
#' @export |
|
| 257 |
#' @rdname group_names |
|
| 258 |
#' @aliases group_n,ReferenceGroups-method |
|
| 259 |
setMethod( |
|
| 260 |
f = "group_n", |
|
| 261 |
signature = "ReferenceGroups", |
|
| 262 | 6x |
definition = function(object) length(group_levels(object)) |
| 263 |
) |
|
| 264 | ||
| 265 |
#' @export |
|
| 266 |
#' @rdname group_names |
|
| 267 |
#' @aliases group_size,ReferenceGroups-method |
|
| 268 |
setMethod( |
|
| 269 |
f = "group_size", |
|
| 270 |
signature = "ReferenceGroups", |
|
| 271 | 5x |
definition = function(object) lengths(group_rows(object)) |
| 272 |
) |
|
| 273 | ||
| 274 |
# Predicates =================================================================== |
|
| 275 |
#' @export |
|
| 276 |
#' @rdname is_assigned |
|
| 277 |
#' @aliases is_assigned,ReferenceGroups-method |
|
| 278 |
setMethod( |
|
| 279 |
f = "is_assigned", |
|
| 280 |
signature = "ReferenceGroups", |
|
| 281 | 6x |
definition = function(object) !is.na(group_names(object)) |
| 282 |
) |
|
| 283 | ||
| 284 |
#' @export |
|
| 285 |
#' @rdname is_assigned |
|
| 286 |
#' @aliases any_assigned,ReferenceGroups-method |
|
| 287 |
setMethod( |
|
| 288 |
f = "any_assigned", |
|
| 289 |
signature = "ReferenceGroups", |
|
| 290 | 3x |
definition = function(object) any(is_assigned(object)) |
| 291 |
) |
|
| 292 | ||
| 293 |
#' @export |
|
| 294 |
#' @rdname is_assigned |
|
| 295 |
#' @aliases all_assigned,ReferenceGroups-method |
|
| 296 |
setMethod( |
|
| 297 |
f = "all_assigned", |
|
| 298 |
signature = "ReferenceGroups", |
|
| 299 | 1x |
definition = function(object) all(is_assigned(object)) |
| 300 |
) |
| 1 |
# COERCION |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# To CompositionMatrix ========================================================= |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname as_composition |
|
| 8 |
#' @aliases as_composition,numeric-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "as_composition", |
|
| 11 |
signature = c(from = "numeric"), |
|
| 12 |
definition = function(from) {
|
|
| 13 | 18x |
from <- matrix(data = from, nrow = 1, ncol = length(from)) |
| 14 | 18x |
methods::callGeneric(from) |
| 15 |
} |
|
| 16 |
) |
|
| 17 | ||
| 18 |
#' @export |
|
| 19 |
#' @rdname as_composition |
|
| 20 |
#' @aliases as_composition,matrix-method |
|
| 21 |
setMethod( |
|
| 22 |
f = "as_composition", |
|
| 23 |
signature = c(from = "matrix"), |
|
| 24 |
definition = function(from) {
|
|
| 25 |
## Validation |
|
| 26 | 27x |
arkhe::assert_type(from, "numeric") |
| 27 | ||
| 28 |
## Make row/column names |
|
| 29 | 27x |
lab <- make_names(x = NULL, n = nrow(from), prefix = "S") |
| 30 | 27x |
rownames(from) <- if (has_rownames(from)) rownames(from) else lab |
| 31 | 27x |
colnames(from) <- make_names(x = colnames(from), n = ncol(from), prefix = "V") |
| 32 | ||
| 33 |
## Close |
|
| 34 | 27x |
totals <- rowSums(from, na.rm = TRUE) |
| 35 | 27x |
from <- from / totals |
| 36 | ||
| 37 | 27x |
.CompositionMatrix(from, totals = unname(totals)) |
| 38 |
} |
|
| 39 |
) |
|
| 40 | ||
| 41 |
#' @export |
|
| 42 |
#' @rdname as_composition |
|
| 43 |
#' @aliases as_composition,data.frame-method |
|
| 44 |
setMethod( |
|
| 45 |
f = "as_composition", |
|
| 46 |
signature = c(from = "data.frame"), |
|
| 47 |
definition = function(from, parts = NULL, groups = NULL, autodetect = TRUE, |
|
| 48 |
verbose = getOption("nexus.verbose")) {
|
|
| 49 |
## Clean row/column names |
|
| 50 | 18x |
lab <- make_names(x = NULL, n = nrow(from), prefix = "S") |
| 51 | 18x |
rownames(from) <- if (has_rownames(from)) rownames(from) else lab |
| 52 | 18x |
colnames(from) <- make_names(x = colnames(from), n = ncol(from), prefix = "V") |
| 53 | ||
| 54 |
## Remove non-numeric columns |
|
| 55 | 18x |
if (is.null(parts)) {
|
| 56 | 17x |
if (isTRUE(autodetect)) {
|
| 57 | 17x |
parts <- arkhe::detect(from, f = is.numeric, margin = 2) |
| 58 | 17x |
if (isTRUE(verbose)) {
|
| 59 | ! |
n <- sum(parts) |
| 60 | ! |
what <- ngettext(n, "Found %g part (%s)", "Found %g parts (%s)") |
| 61 | ! |
cols <- paste0(colnames(from)[parts], collapse = ", ") |
| 62 | ! |
message(sprintf(what, n, cols)) |
| 63 |
} |
|
| 64 |
} else {
|
|
| 65 | ! |
arkhe::assert_filled(parts) |
| 66 |
} |
|
| 67 |
} else {
|
|
| 68 | 1x |
if (is.numeric(parts)) parts <- seq_len(ncol(from)) %in% parts |
| 69 | ! |
if (is.character(parts)) parts <- colnames(from) %in% parts |
| 70 |
} |
|
| 71 | 18x |
coda <- from[, parts, drop = FALSE] |
| 72 | 18x |
arkhe::assert_filled(coda) |
| 73 | ||
| 74 |
## Build matrix |
|
| 75 | 18x |
coda <- data.matrix(coda, rownames.force = NA) |
| 76 | 18x |
totals <- rowSums(coda, na.rm = TRUE) |
| 77 | 18x |
coda <- coda / totals |
| 78 | ||
| 79 | 18x |
z <- .CompositionMatrix(coda, totals = unname(totals)) |
| 80 | 17x |
if (is.null(groups)) return(z) |
| 81 | ||
| 82 |
## Group names |
|
| 83 | 1x |
grp <- from[groups] |
| 84 | 1x |
group(z, by = grp, verbose = verbose) |
| 85 |
} |
|
| 86 |
) |
|
| 87 | ||
| 88 |
# To amounts =================================================================== |
|
| 89 |
#' @export |
|
| 90 |
#' @rdname as_amounts |
|
| 91 |
#' @aliases as_amounts,CompositionMatrix-method |
|
| 92 |
setMethod( |
|
| 93 |
f = "as_amounts", |
|
| 94 |
signature = c(from = "CompositionMatrix"), |
|
| 95 |
definition = function(from) {
|
|
| 96 | 2x |
methods::as(from, "matrix") * totals(from) |
| 97 |
} |
|
| 98 |
) |
|
| 99 | ||
| 100 |
# To data.frame ================================================================ |
|
| 101 |
#' @method as.data.frame CompositionMatrix |
|
| 102 |
#' @export |
|
| 103 |
as.data.frame.CompositionMatrix <- function(x, ..., group_var = ".group", group_after = 0) {
|
|
| 104 | 1x |
z <- as.data.frame(methods::as(x, "matrix"), row.names = rownames(x), ...) |
| 105 | ||
| 106 | ! |
if (!is_grouped(x)) return(z) |
| 107 | 1x |
arkhe::append_column(z, group_names(x), after = group_after, var = group_var) |
| 108 |
} |
|
| 109 | ||
| 110 |
#' @export |
|
| 111 |
#' @rdname as.data.frame |
|
| 112 |
#' @aliases as.data.frame,CompositionMatrix-method |
|
| 113 |
setMethod("as.data.frame", "CompositionMatrix", as.data.frame.CompositionMatrix)
|
|
| 114 | ||
| 115 |
#' @method as.data.frame LogRatio |
|
| 116 |
#' @export |
|
| 117 |
as.data.frame.LogRatio <- function(x, ..., group_var = ".group", group_after = 0) {
|
|
| 118 | 1x |
z <- as.data.frame(methods::as(x, "matrix"), row.names = rownames(x), ...) |
| 119 | ||
| 120 |
## Add columns labels |
|
| 121 | 1x |
lab <- labels(x) |
| 122 | 1x |
for (j in seq_len(ncol(z))) attr(z[[j]], "label") <- lab[[j]] |
| 123 | ||
| 124 | 1x |
if (!is_grouped(x)) return(z) |
| 125 | ! |
arkhe::append_column(z, group_names(x), after = group_after, var = group_var) |
| 126 |
} |
|
| 127 | ||
| 128 |
#' @export |
|
| 129 |
#' @rdname as.data.frame |
|
| 130 |
#' @aliases as.data.frame,LogRatio-method |
|
| 131 |
setMethod("as.data.frame", "LogRatio", as.data.frame.LogRatio)
|
|
| 132 | ||
| 133 |
#' @method as.data.frame OutlierIndex |
|
| 134 |
#' @export |
|
| 135 |
as.data.frame.OutlierIndex <- function(x, row.names = rownames(x), |
|
| 136 |
optional = FALSE, ...) {
|
|
| 137 | ! |
as.data.frame(x@standard, row.names = row.names, optional = optional) |
| 138 |
} |
|
| 139 | ||
| 140 |
#' @export |
|
| 141 |
#' @rdname as.data.frame |
|
| 142 |
#' @aliases as.data.frame,OutlierIndex-method |
|
| 143 |
setMethod("as.data.frame", "OutlierIndex", as.data.frame.OutlierIndex)
|
| 1 |
# SCALE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Scale ======================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @method scale CompositionMatrix |
|
| 8 |
scale.CompositionMatrix <- function(x, center = TRUE, scale = TRUE) {
|
|
| 9 | ! |
if (isFALSE(center) & isFALSE(scale)) return(x) |
| 10 | ||
| 11 | 1x |
y <- x |
| 12 | 1x |
if (!isFALSE(center)) {
|
| 13 | 1x |
if (isTRUE(center)) center <- mean(x) |
| 14 | 1x |
arkhe::assert_type(center, "numeric") |
| 15 | 1x |
arkhe::assert_length(center, NCOL(x)) |
| 16 | ||
| 17 | 1x |
y <- perturbation(y, 1 / center) |
| 18 |
} |
|
| 19 | ||
| 20 | 1x |
if (!isFALSE(scale)) {
|
| 21 | 1x |
if (isTRUE(scale)) scale <- sqrt(mean(diag(covariance(x, center = TRUE)))) |
| 22 | 1x |
arkhe::assert_scalar(scale, "numeric") |
| 23 | ||
| 24 | 1x |
y <- powering(y, 1 / scale) |
| 25 |
} |
|
| 26 | ||
| 27 | 1x |
y |
| 28 |
} |
|
| 29 | ||
| 30 |
#' @export |
|
| 31 |
#' @rdname scale |
|
| 32 |
#' @aliases scale,CompositionMatrix-method |
|
| 33 |
setMethod("scale", "CompositionMatrix", scale.CompositionMatrix)
|
| 1 |
# DATA TRANSFORMATION: CENTERED LOG RATIO |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# CLR ========================================================================== |
|
| 6 |
clr_base <- function(D, weights = rep(1 / D, D)) {
|
|
| 7 | 21x |
diag(D) - matrix(data = weights, nrow = D, ncol = D) |
| 8 |
} |
|
| 9 | ||
| 10 |
#' @export |
|
| 11 |
#' @rdname transform_clr |
|
| 12 |
#' @aliases transform_clr,CompositionMatrix-method |
|
| 13 |
setMethod( |
|
| 14 |
f = "transform_clr", |
|
| 15 |
signature = c(object = "CompositionMatrix"), |
|
| 16 |
definition = function(object, weights = FALSE) {
|
|
| 17 | 18x |
D <- ncol(object) |
| 18 | 18x |
parts <- colnames(object) |
| 19 | ||
| 20 | 18x |
weights <- make_weights(object, weights = weights) |
| 21 | 18x |
base <- clr_base(D, weights = weights) |
| 22 | 18x |
clr <- log(object, base = exp(1)) %*% base |
| 23 | 18x |
dimnames(clr) <- dimnames(object) |
| 24 | ||
| 25 | 18x |
.CLR( |
| 26 | 18x |
clr, |
| 27 | 18x |
parts = parts, |
| 28 | 18x |
ratio = parts, |
| 29 | 18x |
order = seq_len(D), |
| 30 | 18x |
base = base, |
| 31 | 18x |
weights = weights, |
| 32 | 18x |
totals = totals(object) |
| 33 |
) |
|
| 34 |
} |
|
| 35 |
) |
|
| 36 | ||
| 37 |
#' @export |
|
| 38 |
#' @rdname transform_clr |
|
| 39 |
#' @aliases transform_clr,GroupedComposition-method |
|
| 40 |
setMethod( |
|
| 41 |
f = "transform_clr", |
|
| 42 |
signature = c(object = "GroupedComposition"), |
|
| 43 |
definition = function(object, weights = FALSE) {
|
|
| 44 | ! |
z <- methods::callNextMethod() |
| 45 | ! |
.GroupedCLR(z, group_indices = group_indices(object), |
| 46 | ! |
group_levels = group_levels(object), |
| 47 | ! |
group_ordered = is_ordered(object)) |
| 48 |
} |
|
| 49 |
) |
|
| 50 | ||
| 51 |
#' @export |
|
| 52 |
#' @rdname transform_clr |
|
| 53 |
#' @aliases transform_clr,ALR-method |
|
| 54 |
setMethod( |
|
| 55 |
f = "transform_clr", |
|
| 56 |
signature = c(object = "ALR"), |
|
| 57 |
definition = function(object) {
|
|
| 58 | 3x |
D <- ncol(object) + 1 |
| 59 | 3x |
w <- object@weights |
| 60 | ||
| 61 | 3x |
base <- clr_base(D, weights = w) |
| 62 | 3x |
clr <- object %*% base[-D, ] |
| 63 | 3x |
dimnames(clr) <- list(rownames(object), object@parts) |
| 64 | ||
| 65 | 3x |
.CLR( |
| 66 | 3x |
clr, |
| 67 | 3x |
parts = object@parts, |
| 68 | 3x |
ratio = object@parts, |
| 69 | 3x |
order = seq_len(D), |
| 70 | 3x |
base = base, |
| 71 | 3x |
weights = w, |
| 72 | 3x |
totals = totals(object) |
| 73 |
) |
|
| 74 |
} |
|
| 75 |
) |
|
| 76 | ||
| 77 |
#' @export |
|
| 78 |
#' @rdname transform_clr |
|
| 79 |
#' @aliases transform_clr,GroupedALR-method |
|
| 80 |
setMethod( |
|
| 81 |
f = "transform_clr", |
|
| 82 |
signature = c(object = "GroupedALR"), |
|
| 83 |
definition = function(object) {
|
|
| 84 | ! |
z <- methods::callNextMethod() |
| 85 | ! |
.GroupedCLR(z, group_indices = group_indices(object), |
| 86 | ! |
group_levels = group_levels(object), |
| 87 | ! |
group_ordered = is_ordered(object)) |
| 88 |
} |
|
| 89 |
) |
| 1 |
# DATA TRANSFORMATION: INVERSE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Backtransform ================================================================ |
|
| 6 |
## CLR ------------------------------------------------------------------------- |
|
| 7 |
#' @export |
|
| 8 |
#' @rdname transform_inverse |
|
| 9 |
#' @aliases transform_inverse,CLR,missing-method |
|
| 10 |
setMethod( |
|
| 11 |
f = "transform_inverse", |
|
| 12 |
signature = c(object = "CLR", origin = "missing"), |
|
| 13 |
definition = function(object) {
|
|
| 14 | 3x |
y <- methods::as(object, "matrix") # Drop slots |
| 15 | 3x |
y <- exp(y) |
| 16 | 3x |
y <- y / rowSums(y) |
| 17 | ||
| 18 | 3x |
dimnames(y) <- list(rownames(object), object@parts) |
| 19 | 3x |
.CompositionMatrix(y, totals = totals(object)) |
| 20 |
} |
|
| 21 |
) |
|
| 22 | ||
| 23 |
#' @export |
|
| 24 |
#' @rdname transform_inverse |
|
| 25 |
#' @aliases transform_inverse,GroupedCLR,missing-method |
|
| 26 |
setMethod( |
|
| 27 |
f = "transform_inverse", |
|
| 28 |
signature = c(object = "GroupedCLR", origin = "missing"), |
|
| 29 |
definition = function(object) {
|
|
| 30 | ! |
z <- methods::callNextMethod() |
| 31 | ! |
.GroupedComposition(z, group_indices = group_indices(object), |
| 32 | ! |
group_levels = group_levels(object), |
| 33 | ! |
group_ordered = is_ordered(object)) |
| 34 |
} |
|
| 35 |
) |
|
| 36 | ||
| 37 |
## ALR ------------------------------------------------------------------------- |
|
| 38 |
#' @export |
|
| 39 |
#' @rdname transform_inverse |
|
| 40 |
#' @aliases transform_inverse,ALR,missing-method |
|
| 41 |
setMethod( |
|
| 42 |
f = "transform_inverse", |
|
| 43 |
signature = c(object = "ALR", origin = "missing"), |
|
| 44 |
definition = function(object) {
|
|
| 45 | 3x |
y <- exp(object) |
| 46 | 3x |
y <- y / (1 + rowSums(y)) |
| 47 | 3x |
z <- 1 - rowSums(y) |
| 48 | ||
| 49 | 3x |
y <- cbind(y, z) |
| 50 | 3x |
dimnames(y) <- list(rownames(object), object@parts) |
| 51 | 3x |
y <- y[, object@order] |
| 52 | ||
| 53 | 3x |
.CompositionMatrix(y, totals = totals(object)) |
| 54 |
} |
|
| 55 |
) |
|
| 56 | ||
| 57 |
#' @export |
|
| 58 |
#' @rdname transform_inverse |
|
| 59 |
#' @aliases transform_inverse,GroupedALR,missing-method |
|
| 60 |
setMethod( |
|
| 61 |
f = "transform_inverse", |
|
| 62 |
signature = c(object = "GroupedALR", origin = "missing"), |
|
| 63 |
definition = function(object) {
|
|
| 64 | ! |
z <- methods::callNextMethod() |
| 65 | ! |
.GroupedComposition(z, group_indices = group_indices(object), |
| 66 | ! |
group_levels = group_levels(object), |
| 67 | ! |
group_ordered = is_ordered(object)) |
| 68 |
} |
|
| 69 |
) |
|
| 70 | ||
| 71 |
## ILR ------------------------------------------------------------------------- |
|
| 72 |
#' @export |
|
| 73 |
#' @rdname transform_inverse |
|
| 74 |
#' @aliases transform_inverse,ILR,missing-method |
|
| 75 |
setMethod( |
|
| 76 |
f = "transform_inverse", |
|
| 77 |
signature = c(object = "ILR", origin = "missing"), |
|
| 78 |
definition = function(object) {
|
|
| 79 | 2x |
y <- tcrossprod(object@.Data, object@base) |
| 80 | 2x |
y <- exp(y) |
| 81 | 2x |
y <- y / rowSums(y) |
| 82 | ||
| 83 | 2x |
dimnames(y) <- list(rownames(object), object@parts) |
| 84 | 2x |
y <- y[, object@order] |
| 85 | ||
| 86 | 2x |
.CompositionMatrix(y, totals = totals(object)) |
| 87 |
} |
|
| 88 |
) |
|
| 89 | ||
| 90 |
#' @export |
|
| 91 |
#' @rdname transform_inverse |
|
| 92 |
#' @aliases transform_inverse,GroupedILR,missing-method |
|
| 93 |
setMethod( |
|
| 94 |
f = "transform_inverse", |
|
| 95 |
signature = c(object = "GroupedILR", origin = "missing"), |
|
| 96 |
definition = function(object) {
|
|
| 97 | ! |
z <- methods::callNextMethod() |
| 98 | ! |
.GroupedComposition(z, group_indices = group_indices(object), |
| 99 | ! |
group_levels = group_levels(object), |
| 100 | ! |
group_ordered = is_ordered(object)) |
| 101 |
} |
|
| 102 |
) |
|
| 103 | ||
| 104 |
#' @export |
|
| 105 |
#' @rdname transform_inverse |
|
| 106 |
#' @aliases transform_inverse,matrix,ILR-method |
|
| 107 |
setMethod( |
|
| 108 |
f = "transform_inverse", |
|
| 109 |
signature = c(object = "matrix", origin = "ILR"), |
|
| 110 |
definition = function(object, origin) {
|
|
| 111 | 1x |
y <- tcrossprod(object, origin@base) |
| 112 | 1x |
y <- exp(y) |
| 113 | 1x |
y <- y / rowSums(y) |
| 114 | ||
| 115 | 1x |
dimnames(y) <- list(rownames(object), origin@parts) |
| 116 | 1x |
y <- y[, origin@order] |
| 117 | ||
| 118 | 1x |
y |
| 119 |
} |
|
| 120 |
) |
| 1 |
# DATA TRANSFORMATION: PIVOT LOG RATIO |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Pivot ======================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname transform_plr |
|
| 8 |
#' @aliases transform_plr,CompositionMatrix-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "transform_plr", |
|
| 11 |
signature = c(object = "CompositionMatrix"), |
|
| 12 |
definition = function(object, pivot = 1) {
|
|
| 13 | 4x |
J <- ncol(object) |
| 14 | 4x |
parts <- colnames(object) |
| 15 | ||
| 16 |
## Reorder |
|
| 17 | 4x |
pivot <- if (is.character(pivot)) which(parts == pivot) else as.integer(pivot) |
| 18 | 4x |
ordering <- c(pivot, which(pivot != seq_len(J))) |
| 19 | 4x |
parts <- parts[ordering] |
| 20 | 4x |
obj <- object[, ordering, drop = FALSE] |
| 21 | ||
| 22 | 4x |
x <- seq_len(J - 1) |
| 23 | 4x |
balances <- diag(sqrt((J - x) / (J - x + 1))) |
| 24 | 4x |
z <- 1 / matrix(data = seq_len(J) - J, nrow = J, ncol = J) |
| 25 | 4x |
z[lower.tri(z)] <- 0 |
| 26 | 4x |
diag(z) <- 1 |
| 27 | 4x |
z <- z[-nrow(z), ] |
| 28 | ||
| 29 | 4x |
H <- t(balances %*% z) |
| 30 | 4x |
plr <- log(obj, base = exp(1)) %*% H |
| 31 | ||
| 32 | 4x |
ratio <- vapply( |
| 33 | 4x |
X = seq_len(J - 1), |
| 34 | 4x |
FUN = function(i, parts) {
|
| 35 | 12x |
j <- length(parts) |
| 36 | 12x |
sprintf("%s/(%s)", parts[1], paste0(parts[(i+1):j], collapse = ","))
|
| 37 |
}, |
|
| 38 | 4x |
FUN.VALUE = character(1), |
| 39 | 4x |
parts = parts |
| 40 |
) |
|
| 41 | 4x |
colnames(plr) <- paste0("Z", seq_len(J - 1))
|
| 42 | 4x |
rownames(plr) <- rownames(object) |
| 43 | ||
| 44 | 4x |
.PLR( |
| 45 | 4x |
plr, |
| 46 | 4x |
parts = parts, |
| 47 | 4x |
ratio = ratio, |
| 48 | 4x |
order = order(ordering), |
| 49 | 4x |
base = H, |
| 50 | 4x |
weights = rep(1 / J, J), |
| 51 | 4x |
totals = totals(object) |
| 52 |
) |
|
| 53 |
} |
|
| 54 |
) |
|
| 55 | ||
| 56 |
#' @export |
|
| 57 |
#' @rdname transform_plr |
|
| 58 |
#' @aliases transform_plr,GroupedComposition-method |
|
| 59 |
setMethod( |
|
| 60 |
f = "transform_plr", |
|
| 61 |
signature = c(object = "GroupedComposition"), |
|
| 62 |
definition = function(object, pivot = 1) {
|
|
| 63 | ! |
z <- methods::callNextMethod() |
| 64 | ! |
.GroupedPLR(z, group_indices = group_indices(object), |
| 65 | ! |
group_levels = group_levels(object), |
| 66 | ! |
group_ordered = is_ordered(object)) |
| 67 |
} |
|
| 68 |
) |
| 1 |
# GENERIC METHODS |
|
| 2 |
#' @include AllClasses.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# S4 dispatch to base S3 generic =============================================== |
|
| 6 |
setGeneric("dist", package = "stats")
|
|
| 7 |
setGeneric("mahalanobis", package = "stats")
|
|
| 8 | ||
| 9 |
# Import S4 generics =========================================================== |
|
| 10 |
#' @importMethodsFrom arkhe describe |
|
| 11 |
#' @importMethodsFrom arkhe replace_NA |
|
| 12 |
#' @importMethodsFrom arkhe replace_zero |
|
| 13 |
#' @importMethodsFrom dimensio pca |
|
| 14 |
NULL |
|
| 15 | ||
| 16 |
# CoDa ========================================================================= |
|
| 17 |
#' Coerce to a Closed Compositional Matrix |
|
| 18 |
#' |
|
| 19 |
#' Coerces an object to a `CompositionMatrix` object. |
|
| 20 |
#' @param from A [`matrix`] or [`data.frame`] to be coerced. |
|
| 21 |
#' @param parts A `vector` giving the index of the column to be used a |
|
| 22 |
#' compositional parts. If `NULL` and `autodetect` is `TRUE` (the default), |
|
| 23 |
#' all `numeric` columns will be used. |
|
| 24 |
#' @param groups An [`integer`] giving the index of the column to be used to |
|
| 25 |
#' group the samples. If `NULL` (the default), no grouping is stored. |
|
| 26 |
#' @param autodetect A [`logical`] scalar: should `numeric` variables be |
|
| 27 |
#' automatically used as compositional parts? |
|
| 28 |
#' @param verbose A [`logical`] scalar: should \R report extra information |
|
| 29 |
#' on progress? |
|
| 30 |
#' @param ... Currently not used. |
|
| 31 |
#' @details |
|
| 32 |
#' See `vignette("nexus")`.
|
|
| 33 |
#' @return A [`CompositionMatrix-class`] object. |
|
| 34 |
#' @example inst/examples/ex-coerce.R |
|
| 35 |
#' @author N. Frerebeau |
|
| 36 |
#' @docType methods |
|
| 37 |
#' @family compositional data tools |
|
| 38 |
#' @aliases as_composition-method |
|
| 39 |
setGeneric( |
|
| 40 |
name = "as_composition", |
|
| 41 |
def = function(from, ...) standardGeneric("as_composition"),
|
|
| 42 |
valueClass = "CompositionMatrix" |
|
| 43 |
) |
|
| 44 | ||
| 45 |
#' Coerce to Amounts |
|
| 46 |
#' |
|
| 47 |
#' @param from A [`CompositionMatrix-class`] object. |
|
| 48 |
#' @param ... Currently not used. |
|
| 49 |
#' @return A [`numeric`] [`matrix`]. |
|
| 50 |
#' @example inst/examples/ex-coerce.R |
|
| 51 |
#' @author N. Frerebeau |
|
| 52 |
#' @docType methods |
|
| 53 |
#' @family compositional data tools |
|
| 54 |
#' @aliases as_amounts-method |
|
| 55 |
setGeneric( |
|
| 56 |
name = "as_amounts", |
|
| 57 |
def = function(from, ...) standardGeneric("as_amounts"),
|
|
| 58 |
valueClass = "matrix" |
|
| 59 |
) |
|
| 60 | ||
| 61 |
#' Data Description |
|
| 62 |
#' |
|
| 63 |
#' Describes an object. |
|
| 64 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 65 |
#' @return |
|
| 66 |
#' `describe()` is called for its side-effects. Invisibly returns `x`. |
|
| 67 |
#' @example inst/examples/ex-describe.R |
|
| 68 |
#' @author N. Frerebeau |
|
| 69 |
#' @docType methods |
|
| 70 |
#' @family data summaries |
|
| 71 |
#' @name describe |
|
| 72 |
#' @rdname describe |
|
| 73 |
NULL |
|
| 74 | ||
| 75 |
# Simplex ====================================================================== |
|
| 76 |
#' Operations in the Simplex |
|
| 77 |
#' |
|
| 78 |
#' Operators performing operations in the simplex. |
|
| 79 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 80 |
#' @param y A [`CompositionMatrix-class`] object or a [`numeric`] vector. |
|
| 81 |
#' @details |
|
| 82 |
#' \describe{
|
|
| 83 |
#' \item{`%perturbe%`}{[Perturbation operation][perturbation()].}
|
|
| 84 |
#' \item{`%power%`}{[Powering operation][powering()].}
|
|
| 85 |
#' } |
|
| 86 |
#' @return |
|
| 87 |
#' A [`CompositionMatrix-class`] object or a [`numeric`] vector (same as `x`). |
|
| 88 |
#' @example inst/examples/ex-arith.R |
|
| 89 |
#' @author N. Frerebeau |
|
| 90 |
#' @docType methods |
|
| 91 |
#' @family operations in the simplex |
|
| 92 |
#' @name arithmetic |
|
| 93 |
#' @rdname arithmetic |
|
| 94 |
NULL |
|
| 95 | ||
| 96 |
#' @rdname arithmetic |
|
| 97 |
#' @aliases `%perturbe%`-method |
|
| 98 |
setGeneric( |
|
| 99 |
name = "%perturbe%", |
|
| 100 | 6x |
def = function(x, y) standardGeneric("%perturbe%")
|
| 101 |
) |
|
| 102 | ||
| 103 |
#' @rdname arithmetic |
|
| 104 |
#' @aliases `%power%`-method |
|
| 105 |
setGeneric( |
|
| 106 |
name = "%power%", |
|
| 107 | 4x |
def = function(x, y) standardGeneric("%power%")
|
| 108 |
) |
|
| 109 | ||
| 110 |
#' Closure Operation |
|
| 111 |
#' |
|
| 112 |
#' Closes compositions to sum to 1. |
|
| 113 |
#' @param x A [`numeric`] vector or matrix. |
|
| 114 |
#' @param total A [numeric] vector specifying the total amount to which the |
|
| 115 |
#' compositions should be closed (defaults to 1). |
|
| 116 |
#' @param na.rm A [`logical`] scalar: should missing values be removed? |
|
| 117 |
#' @param ... Currently not used. |
|
| 118 |
#' @return A [`numeric`] vector or matrix (same as `x`). |
|
| 119 |
#' @example inst/examples/ex-arith.R |
|
| 120 |
#' @author N. Frerebeau |
|
| 121 |
#' @docType methods |
|
| 122 |
#' @family operations in the simplex |
|
| 123 |
#' @aliases closure-method |
|
| 124 |
setGeneric( |
|
| 125 |
name = "closure", |
|
| 126 | 51x |
def = function(x, ...) standardGeneric("closure")
|
| 127 |
) |
|
| 128 | ||
| 129 |
#' Perturbation Operation |
|
| 130 |
#' |
|
| 131 |
#' Perturbation of two compositions. |
|
| 132 |
#' @param x,y A [`numeric`] vector of compositional data or a |
|
| 133 |
#' [`CompositionMatrix-class`] object. |
|
| 134 |
#' @param ... Currently not used. |
|
| 135 |
#' @details |
|
| 136 |
#' In compositional geometry, perturbation plays the role of sum (translation). |
|
| 137 |
#' It is the closed component-wise product of two compositions. |
|
| 138 |
#' @return A [`numeric`] vector. |
|
| 139 |
#' @example inst/examples/ex-arith.R |
|
| 140 |
#' @author N. Frerebeau |
|
| 141 |
#' @docType methods |
|
| 142 |
#' @family operations in the simplex |
|
| 143 |
#' @aliases perturbation-method |
|
| 144 |
setGeneric( |
|
| 145 |
name = "perturbation", |
|
| 146 | 5x |
def = function(x, y, ...) standardGeneric("perturbation")
|
| 147 |
) |
|
| 148 | ||
| 149 |
#' Powering Operation |
|
| 150 |
#' |
|
| 151 |
#' Perturbation of two compositions. |
|
| 152 |
#' @param x A [`numeric`] vector of compositional data or a |
|
| 153 |
#' [`CompositionMatrix-class`] object. |
|
| 154 |
#' @param a A [`numeric`] constant. |
|
| 155 |
#' @param ... Currently not used. |
|
| 156 |
#' @details |
|
| 157 |
#' In compositional geometry, powering replaces the product of a vector by a |
|
| 158 |
#' scalar (scaling) and is defined as the closed powering of the components by |
|
| 159 |
#' a given scalar. |
|
| 160 |
#' @return A [`numeric`] vector. |
|
| 161 |
#' @example inst/examples/ex-arith.R |
|
| 162 |
#' @author N. Frerebeau |
|
| 163 |
#' @docType methods |
|
| 164 |
#' @family operations in the simplex |
|
| 165 |
#' @aliases powering-method |
|
| 166 |
setGeneric( |
|
| 167 |
name = "powering", |
|
| 168 | 2x |
def = function(x, a, ...) standardGeneric("powering")
|
| 169 |
) |
|
| 170 | ||
| 171 |
#' Scalar Product |
|
| 172 |
#' |
|
| 173 |
#' Computes the Aitchison scalar product of two compositions. |
|
| 174 |
#' @param x,y A [`CompositionMatrix-class`] object. |
|
| 175 |
#' @param ... Currently not used. |
|
| 176 |
#' @return A [`numeric`] vector. |
|
| 177 |
#' @example inst/examples/ex-arith.R |
|
| 178 |
#' @author N. Frerebeau |
|
| 179 |
#' @docType methods |
|
| 180 |
#' @family operations in the simplex |
|
| 181 |
#' @aliases scalar-method |
|
| 182 |
setGeneric( |
|
| 183 |
name = "scalar", |
|
| 184 | 303x |
def = function(x, y, ...) standardGeneric("scalar")
|
| 185 |
) |
|
| 186 | ||
| 187 |
# Extract ====================================================================== |
|
| 188 |
## Subset ---------------------------------------------------------------------- |
|
| 189 |
#' Extract or Replace Parts of an Object |
|
| 190 |
#' |
|
| 191 |
#' Operators acting on objects to extract or replace parts. |
|
| 192 |
#' @param x An object from which to extract element(s) or in which to replace |
|
| 193 |
#' element(s). |
|
| 194 |
#' @param i,j Indices specifying elements to extract or replace. Indices are |
|
| 195 |
#' [`numeric`], [`integer`] or [`character`] vectors or empty (missing) or |
|
| 196 |
#' `NULL`. Numeric values are coerced to [`integer`] as by [as.integer()]. |
|
| 197 |
#' Character vectors will be matched to the name of the elements. |
|
| 198 |
#' An empty index (a comma separated blank) indicates that all entries in that |
|
| 199 |
#' dimension are selected. |
|
| 200 |
#' @param value A possible value for the element(s) of `x`. |
|
| 201 |
#' @param drop A [`logical`] scalar: should the result be coerced to |
|
| 202 |
#' the lowest possible dimension? This only works for extracting elements, |
|
| 203 |
#' not for the replacement. Defaults to `FALSE`. |
|
| 204 |
#' @param ... Currently not used. |
|
| 205 |
# @section Subcomposition: |
|
| 206 |
# If `drop` is `FALSE`, subsetting some of the possible components of a |
|
| 207 |
# [`CompositionMatrix-class`] object will produce a closed *subcomposition* |
|
| 208 |
# (see examples). |
|
| 209 |
#' @return |
|
| 210 |
#' A subsetted object of the same sort as `x`. |
|
| 211 |
#' @example inst/examples/ex-subset.R |
|
| 212 |
#' @author N. Frerebeau |
|
| 213 |
#' @docType methods |
|
| 214 |
#' @family subsetting methods |
|
| 215 |
#' @name subset |
|
| 216 |
#' @rdname subset |
|
| 217 |
NULL |
|
| 218 | ||
| 219 |
#' Combine Two Composition Matrices |
|
| 220 |
#' |
|
| 221 |
#' @param x,y A [`CompositionMatrix-class`] object. |
|
| 222 |
#' @details |
|
| 223 |
#' `rbind2()` combine by rows. |
|
| 224 |
#' @return |
|
| 225 |
#' A [`CompositionMatrix-class`] objects. |
|
| 226 |
#' @example inst/examples/ex-split.R |
|
| 227 |
#' @author N. Frerebeau |
|
| 228 |
#' @docType methods |
|
| 229 |
#' @family subsetting methods |
|
| 230 |
#' @name bind |
|
| 231 |
#' @rdname bind |
|
| 232 |
NULL |
|
| 233 | ||
| 234 |
## Mutators -------------------------------------------------------------------- |
|
| 235 |
#' Weights |
|
| 236 |
#' |
|
| 237 |
#' Extract weights from an object. |
|
| 238 |
#' @param object An object for which the extraction of weights is meaningful. |
|
| 239 |
# @param value A possible value for the element(s) of `object`. |
|
| 240 |
#' @param ... Currently not used. |
|
| 241 |
# @example inst/examples/ex-mutators.R |
|
| 242 |
#' @author N. Frerebeau |
|
| 243 |
#' @docType methods |
|
| 244 |
#' @family mutators |
|
| 245 |
#' @name weights |
|
| 246 |
#' @rdname weights |
|
| 247 |
#' @aliases get set |
|
| 248 |
NULL |
|
| 249 | ||
| 250 |
#' Labels |
|
| 251 |
#' |
|
| 252 |
#' Find a suitable set of labels from an object. |
|
| 253 |
#' @param object An object from which to get the labels. |
|
| 254 |
# @param value A possible value for the element(s) of `object`. |
|
| 255 |
#' @param ... Currently not used. |
|
| 256 |
# @example inst/examples/ex-mutators.R |
|
| 257 |
#' @author N. Frerebeau |
|
| 258 |
#' @docType methods |
|
| 259 |
#' @family mutators |
|
| 260 |
#' @name labels |
|
| 261 |
#' @rdname labels |
|
| 262 |
NULL |
|
| 263 | ||
| 264 |
#' Row Sums |
|
| 265 |
#' |
|
| 266 |
#' Retrieves or defines the row sums (before [closure][closure()]). |
|
| 267 |
#' @param object An object from which to get or set `totals`. |
|
| 268 |
#' @param value A possible value for the `totals` of `object`. |
|
| 269 |
#' @return |
|
| 270 |
#' * `totals() <- value` returns an object of the same sort as `object` with |
|
| 271 |
#' the new row sums assigned. |
|
| 272 |
#' * `totals()` returns the row sums of `object`. |
|
| 273 |
#' @example inst/examples/ex-coerce.R |
|
| 274 |
#' @author N. Frerebeau |
|
| 275 |
#' @docType methods |
|
| 276 |
#' @family mutators |
|
| 277 |
#' @aliases totals-method |
|
| 278 |
setGeneric( |
|
| 279 |
name = "totals", |
|
| 280 | 926x |
def = function(object) standardGeneric("totals")
|
| 281 |
) |
|
| 282 | ||
| 283 |
#' @rdname totals |
|
| 284 |
setGeneric( |
|
| 285 |
name = "totals<-", |
|
| 286 | 3x |
def = function(object, value) standardGeneric("totals<-")
|
| 287 |
) |
|
| 288 | ||
| 289 |
## Coerce ---------------------------------------------------------------------- |
|
| 290 |
#' Coerce to a Data Frame |
|
| 291 |
#' |
|
| 292 |
#' @param x An \R object (typically, a [`CompositionMatrix-class`] object). |
|
| 293 |
#' @param row.names A [`character`] vector giving the row names for the data |
|
| 294 |
#' frame, or `NULL`. |
|
| 295 |
#' @param optional A [`logical`] scalar: should the names of the variables in |
|
| 296 |
#' the data frame be checked? If `FALSE` then the names of the variables in the |
|
| 297 |
#' data frame are checked to ensure that they are syntactically valid variable |
|
| 298 |
#' names and are not duplicated. |
|
| 299 |
#' @param group_var A [`character`] string specifying the name of the column to |
|
| 300 |
#' create for group attribution (only used if `x` is [grouped][group()]). |
|
| 301 |
#' @param group_after An [`integer`] specifying a subscript, after which the new |
|
| 302 |
#' `group_var` column is to be appended (only used if `x` is [grouped][group()]). |
|
| 303 |
#' @param ... Further parameters to be passed to |
|
| 304 |
#' [`as.data.frame()`][base::as.data.frame]. |
|
| 305 |
#' @return |
|
| 306 |
#' A [`data.frame`]. |
|
| 307 |
#' @example inst/examples/ex-coerce.R |
|
| 308 |
#' @author N. Frerebeau |
|
| 309 |
#' @docType methods |
|
| 310 |
#' @family mutators |
|
| 311 |
#' @name as.data.frame |
|
| 312 |
#' @rdname as.data.frame |
|
| 313 |
NULL |
|
| 314 | ||
| 315 |
#' Matrix Transpose |
|
| 316 |
#' |
|
| 317 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 318 |
#' @return |
|
| 319 |
#' A `matrix`, with dim and dimnames constructed appropriately from those of `x`. |
|
| 320 |
#' @note |
|
| 321 |
#' Implemented only to ensure that `t()` always returns a base `matrix`. |
|
| 322 |
#' @example inst/examples/ex-subset.R |
|
| 323 |
#' @author N. Frerebeau |
|
| 324 |
#' @docType methods |
|
| 325 |
# @family mutators |
|
| 326 |
#' @keywords internal |
|
| 327 |
#' @name t |
|
| 328 |
#' @rdname t |
|
| 329 |
NULL |
|
| 330 | ||
| 331 |
# Groups ======================================================================= |
|
| 332 |
#' Group by One or More Variables |
|
| 333 |
#' |
|
| 334 |
#' Define or remove the (reference) groups to which the observations belong. |
|
| 335 |
#' @param object An \R object (typically, a [`CompositionMatrix-class`] object). |
|
| 336 |
#' @param by A possible value for the groups of `object` (typically, a |
|
| 337 |
#' [`character`] vector). If `value` is a [`list`], |
|
| 338 |
#' [`interaction(by)`][interaction()] defines the grouping. |
|
| 339 |
#' @param add A [`logical`] scalar. If `TRUE`, add to existing groups. |
|
| 340 |
#' @param verbose A [`logical`] scalar: should \R report extra information |
|
| 341 |
#' on progress? |
|
| 342 |
#' @param ... Further parameters to be passed to internal methods. |
|
| 343 |
#' @details |
|
| 344 |
#' Missing values (`NA`) can be used to specify that a sample does not belong |
|
| 345 |
#' to any group. |
|
| 346 |
#' @return |
|
| 347 |
#' * `group()` returns a grouped object of the same sort as `object`. |
|
| 348 |
#' * `ungroup()` returns an ungrouped object of the same sort as `object`. |
|
| 349 |
#' @example inst/examples/ex-group.R |
|
| 350 |
#' @author N. Frerebeau |
|
| 351 |
#' @docType methods |
|
| 352 |
#' @family grouping methods |
|
| 353 |
#' @aliases group-method |
|
| 354 |
setGeneric( |
|
| 355 |
name = "group", |
|
| 356 | 22x |
def = function(object, ...) standardGeneric("group")
|
| 357 |
) |
|
| 358 | ||
| 359 |
#' @rdname group |
|
| 360 |
setGeneric( |
|
| 361 |
name = "ungroup", |
|
| 362 | 22x |
def = function(object, ...) standardGeneric("ungroup")
|
| 363 |
) |
|
| 364 | ||
| 365 |
#' Grouped Data |
|
| 366 |
#' |
|
| 367 |
#' Retrieve the (reference) groups to which the observations belong. |
|
| 368 |
#' @param object A [grouped][group()] \R object. |
|
| 369 |
#' @return |
|
| 370 |
#' * `is_assigned()` returns a [`logical`] vector specifying whether or |
|
| 371 |
#' not an observation belongs to a group. |
|
| 372 |
#' * `any_assigned()` returns an [`logical`] scalar specifying if any |
|
| 373 |
#' observation belongs to a group. |
|
| 374 |
#' * `all_assigned()` returns an [`logical`] scalar specifying if all |
|
| 375 |
#' observations belong to a group. |
|
| 376 |
#' @example inst/examples/ex-group.R |
|
| 377 |
#' @author N. Frerebeau |
|
| 378 |
#' @docType methods |
|
| 379 |
#' @family grouping methods |
|
| 380 |
#' @aliases is_assigned-method |
|
| 381 |
setGeneric( |
|
| 382 |
name = "is_assigned", |
|
| 383 | 6x |
def = function(object) standardGeneric("is_assigned")
|
| 384 |
) |
|
| 385 | ||
| 386 |
#' @rdname is_assigned |
|
| 387 |
#' @aliases any_assigned-method |
|
| 388 |
setGeneric( |
|
| 389 |
name = "any_assigned", |
|
| 390 | 3x |
def = function(object) standardGeneric("any_assigned")
|
| 391 |
) |
|
| 392 | ||
| 393 |
#' @rdname is_assigned |
|
| 394 |
#' @aliases any_assigned-method |
|
| 395 |
setGeneric( |
|
| 396 |
name = "all_assigned", |
|
| 397 | 1x |
def = function(object) standardGeneric("all_assigned")
|
| 398 |
) |
|
| 399 | ||
| 400 |
#' Grouping Metadata |
|
| 401 |
#' |
|
| 402 |
#' Retrieve the (reference) groups to which the observations belong. |
|
| 403 |
#' @param object A [grouped][group()] \R object. |
|
| 404 |
#' @param exclude A [`character`] vector of values to be excluded when forming |
|
| 405 |
#' the set of levels. |
|
| 406 |
#' @param ... Currently not used. |
|
| 407 |
#' @return |
|
| 408 |
#' * `group_levels()` returns a [`character`] vector giving the group |
|
| 409 |
#' names. |
|
| 410 |
#' * `group_size()` returns an [`integer`] vector giving the size of each |
|
| 411 |
#' group. |
|
| 412 |
#' * `group_n()` gives the total number of groups. |
|
| 413 |
#' * `group_names()` returns a [`character`] vector giving the name of |
|
| 414 |
#' the group that each observation belongs to. |
|
| 415 |
#' * `group_factor()` returns a [`factor`] vector giving the name of |
|
| 416 |
#' the group that each observation belongs to. |
|
| 417 |
#' * `group_indices()` returns an [`integer`] vector giving the group |
|
| 418 |
#' that each value belongs to. |
|
| 419 |
#' * `group_rows()` returns a `list` of [`integer`] vectors giving the |
|
| 420 |
#' observation that each group contains. |
|
| 421 |
#' @example inst/examples/ex-group.R |
|
| 422 |
#' @author N. Frerebeau |
|
| 423 |
#' @docType methods |
|
| 424 |
#' @family grouping methods |
|
| 425 |
#' @aliases group_names-method |
|
| 426 |
setGeneric( |
|
| 427 |
name = "group_names", |
|
| 428 | 115x |
def = function(object) standardGeneric("group_names")
|
| 429 |
) |
|
| 430 | ||
| 431 |
#' @rdname group_names |
|
| 432 |
#' @aliases group_levels-method |
|
| 433 |
setGeneric( |
|
| 434 |
name = "group_levels", |
|
| 435 | 234x |
def = function(object) standardGeneric("group_levels")
|
| 436 |
) |
|
| 437 | ||
| 438 |
#' @rdname group_names |
|
| 439 |
#' @aliases group_factor-method |
|
| 440 |
setGeneric( |
|
| 441 |
name = "group_factor", |
|
| 442 | 101x |
def = function(object, ...) standardGeneric("group_factor")
|
| 443 |
) |
|
| 444 | ||
| 445 |
#' @rdname group_names |
|
| 446 |
#' @aliases group_rows-method |
|
| 447 |
setGeneric( |
|
| 448 |
name = "group_rows", |
|
| 449 | 18x |
def = function(object) standardGeneric("group_rows")
|
| 450 |
) |
|
| 451 | ||
| 452 |
#' @rdname group_names |
|
| 453 |
#' @aliases group_n-method |
|
| 454 |
setGeneric( |
|
| 455 |
name = "group_n", |
|
| 456 | 6x |
def = function(object) standardGeneric("group_n")
|
| 457 |
) |
|
| 458 | ||
| 459 |
#' @rdname group_names |
|
| 460 |
#' @aliases group_size-method |
|
| 461 |
setGeneric( |
|
| 462 |
name = "group_size", |
|
| 463 | 5x |
def = function(object) standardGeneric("group_size")
|
| 464 |
) |
|
| 465 | ||
| 466 |
#' @rdname group_names |
|
| 467 |
#' @aliases group_indices-method |
|
| 468 |
setGeneric( |
|
| 469 |
name = "group_indices", |
|
| 470 | 117x |
def = function(object) standardGeneric("group_indices")
|
| 471 |
) |
|
| 472 | ||
| 473 |
#' Divide into Groups |
|
| 474 |
#' |
|
| 475 |
#' Divides a compositional matrix by groups. |
|
| 476 |
#' @param object,x A [`CompositionMatrix-class`] object. |
|
| 477 |
#' @param f A `factor` in the sense that [`as.factor(f)`][as.factor()] defines |
|
| 478 |
#' the grouping, or a list of such factors in which case their interaction is |
|
| 479 |
#' used for the grouping (see [base::split()]). |
|
| 480 |
#' @param drop A [`logical`] scalar: should levels that do not occur be dropped? |
|
| 481 |
#' @param ... Currently not used. |
|
| 482 |
#' @return |
|
| 483 |
#' A `list` of [`CompositionMatrix-class`] objects. |
|
| 484 |
#' @example inst/examples/ex-split.R |
|
| 485 |
#' @author N. Frerebeau |
|
| 486 |
#' @docType methods |
|
| 487 |
#' @family grouping methods |
|
| 488 |
#' @aliases group_split-method |
|
| 489 |
setGeneric( |
|
| 490 |
name = "group_split", |
|
| 491 | 6x |
def = function(object, ...) standardGeneric("group_split")
|
| 492 |
) |
|
| 493 | ||
| 494 |
#' Group-based Subset |
|
| 495 |
#' |
|
| 496 |
#' @param object A [`GroupedComposition-class`] object. |
|
| 497 |
#' @param which A [`character`] vector specifying the [groups][group()] of |
|
| 498 |
#' `object` to extract. |
|
| 499 |
#' @param ... Currently not used. |
|
| 500 |
#' @return |
|
| 501 |
#' A [`CompositionMatrix-class`] object. |
|
| 502 |
#' @example inst/examples/ex-group.R |
|
| 503 |
#' @author N. Frerebeau |
|
| 504 |
#' @docType methods |
|
| 505 |
#' @family grouping methods |
|
| 506 |
#' @aliases group_subset-method |
|
| 507 |
setGeneric( |
|
| 508 |
name = "group_subset", |
|
| 509 | 1x |
def = function(object, ...) standardGeneric("group_subset")
|
| 510 |
) |
|
| 511 | ||
| 512 |
# Tools ======================================================================== |
|
| 513 |
#' Chemical Elements and Oxides |
|
| 514 |
#' |
|
| 515 |
#' Identify oxides and major, minor and traces elements in a compositional data |
|
| 516 |
#' matrix. |
|
| 517 |
#' @param object A [`CompositionMatrix-class`] object. |
|
| 518 |
#' @param min A length-one [`numeric`] vector specifying the lower bound for |
|
| 519 |
#' element identification. |
|
| 520 |
#' @param max A length-one [`numeric`] vector specifying the upper bound for |
|
| 521 |
#' element identification. |
|
| 522 |
#' @param ... Currently not used. |
|
| 523 |
#' @details |
|
| 524 |
#' There is no definite classification of what are the major, minor and trace |
|
| 525 |
#' elements are. By default, the following rule of thumb is used: |
|
| 526 |
#' \describe{
|
|
| 527 |
#' \item{major elements}{The major elements are those that define the material
|
|
| 528 |
#' under study. Major elements usually have concentrations of above 1%.} |
|
| 529 |
#' \item{minor elements}{Minor elements usually have concentrations between
|
|
| 530 |
#' 1% and 0.1%} |
|
| 531 |
#' \item{trace elements}{Trace elements usually have concentrations of less
|
|
| 532 |
#' than 0.1%.} |
|
| 533 |
#' } |
|
| 534 |
#' @note |
|
| 535 |
#' `is_oxide()` uses a regular expression (it does not check if elements exist |
|
| 536 |
#' or if stoichiometry is valid). |
|
| 537 |
#' @return A [`logical`] vector. |
|
| 538 |
#' @example inst/examples/ex-chemistry.R |
|
| 539 |
#' @author N. Frerebeau |
|
| 540 |
#' @docType methods |
|
| 541 |
#' @family tools |
|
| 542 |
#' @name chemistry |
|
| 543 |
#' @rdname chemistry |
|
| 544 |
NULL |
|
| 545 | ||
| 546 |
#' @rdname chemistry |
|
| 547 |
#' @aliases is_element_major-method |
|
| 548 |
setGeneric( |
|
| 549 |
name = "is_element_major", |
|
| 550 |
def = function(object, ...) standardGeneric("is_element_major"),
|
|
| 551 |
valueClass = "logical" |
|
| 552 |
) |
|
| 553 | ||
| 554 |
#' @rdname chemistry |
|
| 555 |
#' @aliases is_element_minor-method |
|
| 556 |
setGeneric( |
|
| 557 |
name = "is_element_minor", |
|
| 558 |
def = function(object, ...) standardGeneric("is_element_minor"),
|
|
| 559 |
valueClass = "logical" |
|
| 560 |
) |
|
| 561 | ||
| 562 |
#' @rdname chemistry |
|
| 563 |
#' @aliases is_element_trace-method |
|
| 564 |
setGeneric( |
|
| 565 |
name = "is_element_trace", |
|
| 566 |
def = function(object, ...) standardGeneric("is_element_trace"),
|
|
| 567 |
valueClass = "logical" |
|
| 568 |
) |
|
| 569 | ||
| 570 |
#' @rdname chemistry |
|
| 571 |
#' @aliases is_oxide-method |
|
| 572 |
setGeneric( |
|
| 573 |
name = "is_oxide", |
|
| 574 |
def = function(object, ...) standardGeneric("is_oxide"),
|
|
| 575 |
valueClass = "logical" |
|
| 576 |
) |
|
| 577 | ||
| 578 |
# Log-Ratio ==================================================================== |
|
| 579 |
## LR -------------------------------------------------------------------------- |
|
| 580 |
#' Pairwise Log-Ratios (LR) |
|
| 581 |
#' |
|
| 582 |
#' Computes all pairwise log-ratio transformation. |
|
| 583 |
#' @param object A [`CompositionMatrix-class`] object. |
|
| 584 |
#' @param weights A [`logical`] scalar: should varying weights (column means) |
|
| 585 |
#' be computed? If `FALSE` (the default), equally-weighted parts are used. |
|
| 586 |
#' Alternatively, a positive [`numeric`] vector of weights can be specified |
|
| 587 |
#' (will be rescaled to sum to \eqn{1}). Weights will be used internally by
|
|
| 588 |
#' other methods (e.g. [variance()]). |
|
| 589 |
#' @param ... Currently not used. |
|
| 590 |
#' @return |
|
| 591 |
#' A [`LR-class`] object. |
|
| 592 |
#' @references |
|
| 593 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 594 |
#' London: Chapman and Hall. |
|
| 595 |
#' |
|
| 596 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 597 |
#' Boca Raton: CRC Press. |
|
| 598 |
#' |
|
| 599 |
#' Greenacre, M. J. (2021). Compositional Data Analysis. *Annual Review of |
|
| 600 |
#' Statistics and Its Application*, 8(1): 271-299. |
|
| 601 |
#' \doi{10.1146/annurev-statistics-042720-124436}.
|
|
| 602 |
#' @example inst/examples/ex-transform-lr.R |
|
| 603 |
#' @author N. Frerebeau |
|
| 604 |
#' @docType methods |
|
| 605 |
#' @family log-ratio transformations |
|
| 606 |
#' @aliases transform_lr-method |
|
| 607 |
setGeneric( |
|
| 608 |
name = "transform_lr", |
|
| 609 |
def = function(object, ...) standardGeneric("transform_lr"),
|
|
| 610 |
valueClass = "LR" |
|
| 611 |
) |
|
| 612 | ||
| 613 |
## CLR ------------------------------------------------------------------------- |
|
| 614 |
#' Centered Log-Ratios (CLR) |
|
| 615 |
#' |
|
| 616 |
#' Computes CLR transformation. |
|
| 617 |
#' @param object A [`CompositionMatrix-class`] object. |
|
| 618 |
#' @param weights A [`logical`] scalar: should varying weights (column means) |
|
| 619 |
#' be used? If `FALSE` (the default), equally-weighted parts are used. |
|
| 620 |
#' Alternatively, a positive [`numeric`] vector of weights can be specified |
|
| 621 |
#' (will be rescaled to sum to \eqn{1}).
|
|
| 622 |
#' @param ... Currently not used. |
|
| 623 |
#' @details |
|
| 624 |
#' The CLR transformation computes the log of each part relative to the |
|
| 625 |
#' geometric mean of all parts. |
|
| 626 |
#' @return |
|
| 627 |
#' A [`CLR-class`] object. |
|
| 628 |
#' @references |
|
| 629 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 630 |
#' London: Chapman and Hall. |
|
| 631 |
#' |
|
| 632 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 633 |
#' Boca Raton: CRC Press. |
|
| 634 |
#' |
|
| 635 |
#' Greenacre, M. J. (2021). Compositional Data Analysis. *Annual Review of |
|
| 636 |
#' Statistics and Its Application*, 8(1): 271-299. |
|
| 637 |
#' \doi{10.1146/annurev-statistics-042720-124436}.
|
|
| 638 |
#' @example inst/examples/ex-transform-clr.R |
|
| 639 |
#' @author N. Frerebeau |
|
| 640 |
#' @docType methods |
|
| 641 |
#' @family log-ratio transformations |
|
| 642 |
#' @aliases transform_clr-method |
|
| 643 |
setGeneric( |
|
| 644 |
name = "transform_clr", |
|
| 645 |
def = function(object, ...) standardGeneric("transform_clr"),
|
|
| 646 |
valueClass = "CLR" |
|
| 647 |
) |
|
| 648 | ||
| 649 |
## ALR ------------------------------------------------------------------------- |
|
| 650 |
#' Additive Log-Ratios (ALR) |
|
| 651 |
#' |
|
| 652 |
#' Computes ALR transformation. |
|
| 653 |
#' @param object A [`CompositionMatrix-class`] object. |
|
| 654 |
#' @param j An [`integer`] giving the index of the rationing part (denominator). |
|
| 655 |
#' @param weights A [`logical`] scalar: should varying weights (column means) |
|
| 656 |
#' be computed? If `FALSE` (the default), equally-weighted parts are used. |
|
| 657 |
#' Alternatively, a positive [`numeric`] vector of weights can be specified |
|
| 658 |
#' (will be rescaled to sum to \eqn{1}). Weights will be used internally by
|
|
| 659 |
#' other methods (e.g. [variance()]). |
|
| 660 |
#' @param ... Currently not used. |
|
| 661 |
#' @details |
|
| 662 |
#' The ALR transformation is the logratio of a pair of parts with respect to a |
|
| 663 |
#' fixed part. |
|
| 664 |
#' @return |
|
| 665 |
#' An [`ALR-class`] object. |
|
| 666 |
#' @references |
|
| 667 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 668 |
#' London: Chapman and Hall. |
|
| 669 |
#' |
|
| 670 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 671 |
#' Boca Raton: CRC Press. |
|
| 672 |
#' |
|
| 673 |
#' Greenacre, M. J. (2021). Compositional Data Analysis. *Annual Review of |
|
| 674 |
#' Statistics and Its Application*, 8(1): 271-299. |
|
| 675 |
#' \doi{10.1146/annurev-statistics-042720-124436}.
|
|
| 676 |
#' @example inst/examples/ex-transform-alr.R |
|
| 677 |
#' @author N. Frerebeau |
|
| 678 |
#' @docType methods |
|
| 679 |
#' @family log-ratio transformations |
|
| 680 |
#' @aliases transform_alr-method |
|
| 681 |
setGeneric( |
|
| 682 |
name = "transform_alr", |
|
| 683 |
def = function(object, ...) standardGeneric("transform_alr"),
|
|
| 684 |
valueClass = "ALR" |
|
| 685 |
) |
|
| 686 | ||
| 687 |
## ILR ------------------------------------------------------------------------- |
|
| 688 |
#' Isometric Log-Ratios (ILR) |
|
| 689 |
#' |
|
| 690 |
#' Computes ILR transformations. |
|
| 691 |
#' @param object A [`CompositionMatrix-class`] object. |
|
| 692 |
#' @param ... Currently not used. |
|
| 693 |
#' @details |
|
| 694 |
#' The ILR transformation provides the coordinates of any composition with |
|
| 695 |
#' respect to a given orthonormal basis. `transform_ilr()` uses the orthonormal |
|
| 696 |
#' basis (Helmert matrix) originally defined by Egozcue *et al.* (2003). |
|
| 697 |
#' @return |
|
| 698 |
#' An [`ILR-class`] object. |
|
| 699 |
#' @references |
|
| 700 |
#' Egozcue, J. J., Pawlowsky-Glahn, V., Mateu-Figueras, G. & Barceló-Vidal, C. |
|
| 701 |
#' (2003). Isometric Logratio Transformations for Compositional Data Analysis. |
|
| 702 |
#' *Mathematical Geology*, 35(3), 279-300. \doi{10.1023/A:1023818214614}.
|
|
| 703 |
#' |
|
| 704 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 705 |
#' Boca Raton: CRC Press. |
|
| 706 |
#' |
|
| 707 |
#' Greenacre, M. J. (2021). Compositional Data Analysis. *Annual Review of |
|
| 708 |
#' Statistics and Its Application*, 8(1): 271-299. |
|
| 709 |
#' \doi{10.1146/annurev-statistics-042720-124436}.
|
|
| 710 |
#' @example inst/examples/ex-transform-ilr.R |
|
| 711 |
#' @author N. Frerebeau |
|
| 712 |
#' @docType methods |
|
| 713 |
#' @family log-ratio transformations |
|
| 714 |
#' @aliases transform_ilr-method |
|
| 715 |
setGeneric( |
|
| 716 |
name = "transform_ilr", |
|
| 717 |
def = function(object, ...) standardGeneric("transform_ilr"),
|
|
| 718 |
valueClass = "ILR" |
|
| 719 |
) |
|
| 720 | ||
| 721 |
#' Univariate Isometric Log-Ratios (ILR) |
|
| 722 |
#' |
|
| 723 |
#' Computes univariate ILR coordinates. |
|
| 724 |
#' @param object A [`CompositionMatrix-class`] object. |
|
| 725 |
#' @param ... Currently not used. |
|
| 726 |
#' @details |
|
| 727 |
#' The ILR transformation provides the coordinates of any composition with |
|
| 728 |
#' respect to a given orthonormal basis. `transform_ilr()` uses the orthonormal |
|
| 729 |
#' basis (Helmert matrix) originally defined by Egozcue *et al.* (2003). |
|
| 730 |
#' @return |
|
| 731 |
#' Same as `object`. |
|
| 732 |
#' @references |
|
| 733 |
#' Filzmoser, P., Hron, K. & Reimann, C. (2009). Univariate Statistical |
|
| 734 |
#' Analysis of Environmental (Compositional) Data: Problems and Possibilities. |
|
| 735 |
#' *Science of The Total Environment*, 407(23), 6100-6108. |
|
| 736 |
#' \doi{10.1016/j.scitotenv.2009.08.008}.
|
|
| 737 |
#' |
|
| 738 |
#' Filzmoser, P., Hron, K. & Reimann, C. (2010). The Bivariate Statistical |
|
| 739 |
#' Analysis of Environmental (Compositional) Data. *Science of The Total |
|
| 740 |
#' Environment*, 408(19), 4230-4238. \doi{10.1016/j.scitotenv.2010.05.011}.
|
|
| 741 |
#' @example inst/examples/ex-transform-ilr.R |
|
| 742 |
#' @author N. Frerebeau |
|
| 743 |
#' @docType methods |
|
| 744 |
# @family log-ratio transformations |
|
| 745 |
#' @aliases univariate_ilr-method |
|
| 746 |
#' @keywords internal |
|
| 747 |
setGeneric( |
|
| 748 |
name = "univariate_ilr", |
|
| 749 | 14x |
def = function(object, ...) standardGeneric("univariate_ilr")
|
| 750 |
) |
|
| 751 | ||
| 752 |
## PLR ------------------------------------------------------------------------- |
|
| 753 |
#' Pivot Log-Ratios (PLR) |
|
| 754 |
#' |
|
| 755 |
#' Computes PLR transformations. |
|
| 756 |
#' @param object A [`CompositionMatrix-class`] object. |
|
| 757 |
#' @param pivot An [`integer`] giving the index of the pivotal variable. |
|
| 758 |
#' @param ... Currently not used. |
|
| 759 |
#' @return |
|
| 760 |
#' A [`PLR-class`] object. |
|
| 761 |
#' @references |
|
| 762 |
#' Fišerová, E. & Hron, K. (2011). On the Interpretation of Orthonormal |
|
| 763 |
#' Coordinates for Compositional Data. *Mathematical Geosciences*, 43(4), |
|
| 764 |
#' 455‑468. \doi{10.1007/s11004-011-9333-x}.
|
|
| 765 |
#' |
|
| 766 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 767 |
#' Boca Raton: CRC Press. |
|
| 768 |
#' |
|
| 769 |
#' Greenacre, M. J. (2021). Compositional Data Analysis. *Annual Review of |
|
| 770 |
#' Statistics and Its Application*, 8(1): 271-299. |
|
| 771 |
#' \doi{10.1146/annurev-statistics-042720-124436}.
|
|
| 772 |
#' |
|
| 773 |
#' Hron, K., Filzmoser, P., de Caritat, P., Fišerová, E. & Gardlo, A. (2017). |
|
| 774 |
#' Weighted Pivot Coordinates for Compositional Data and Their Application to |
|
| 775 |
#' Geochemical Mapping. *Mathematical Geosciences*, 49(6), 797-814. |
|
| 776 |
#' \doi{10.1007/s11004-017-9684-z}.
|
|
| 777 |
#' @example inst/examples/ex-transform-ilr.R |
|
| 778 |
#' @author N. Frerebeau |
|
| 779 |
#' @docType methods |
|
| 780 |
#' @family log-ratio transformations |
|
| 781 |
#' @aliases transform_plr-method |
|
| 782 |
setGeneric( |
|
| 783 |
name = "transform_plr", |
|
| 784 |
def = function(object, ...) standardGeneric("transform_plr"),
|
|
| 785 |
valueClass = "PLR" |
|
| 786 |
) |
|
| 787 | ||
| 788 |
## Inverse --------------------------------------------------------------------- |
|
| 789 |
#' Inverse Log-Ratio Transformation |
|
| 790 |
#' |
|
| 791 |
#' Computes inverse log-ratio transformations. |
|
| 792 |
#' @param object A [`LogRatio-class`] object. |
|
| 793 |
#' @param origin A [`LogRatio-class`] object to be used for the inverse |
|
| 794 |
#' transformation. |
|
| 795 |
#' @param ... Currently not used. |
|
| 796 |
#' @return |
|
| 797 |
#' A [`CompositionMatrix-class`] object. |
|
| 798 |
#' @references |
|
| 799 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 800 |
#' London: Chapman and Hall. |
|
| 801 |
#' |
|
| 802 |
#' Egozcue, J. J., Pawlowsky-Glahn, V., Mateu-Figueras, G. & Barceló-Vidal, C. |
|
| 803 |
#' (2003). Isometric Logratio Transformations for Compositional Data Analysis. |
|
| 804 |
#' *Mathematical Geology*, 35(3), 279-300. \doi{10.1023/A:1023818214614}.
|
|
| 805 |
#' |
|
| 806 |
#' Fišerová, E. & Hron, K. (2011). On the Interpretation of Orthonormal |
|
| 807 |
#' Coordinates for Compositional Data. *Mathematical Geosciences*, 43(4), |
|
| 808 |
#' 455‑468. \doi{10.1007/s11004-011-9333-x}.
|
|
| 809 |
#' |
|
| 810 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 811 |
#' Boca Raton: CRC Press. |
|
| 812 |
#' @example inst/examples/ex-transform-clr.R |
|
| 813 |
#' @author N. Frerebeau |
|
| 814 |
#' @docType methods |
|
| 815 |
#' @family log-ratio transformations |
|
| 816 |
#' @aliases transform_inverse-method |
|
| 817 |
setGeneric( |
|
| 818 |
name = "transform_inverse", |
|
| 819 |
def = function(object, origin, ...) standardGeneric("transform_inverse"),
|
|
| 820 |
valueClass = "matrix" |
|
| 821 |
) |
|
| 822 | ||
| 823 |
# Statistics =================================================================== |
|
| 824 |
#' Compute Summary Statistics of Data Subsets |
|
| 825 |
#' |
|
| 826 |
#' Splits the data into subsets, computes summary statistics for each, and |
|
| 827 |
#' returns the result. |
|
| 828 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 829 |
#' @param by A `vector` or a list of grouping elements, each as long as the |
|
| 830 |
#' variables in `x` (see [group()]). |
|
| 831 |
#' @param FUN A [`function`] to compute the summary statistics. |
|
| 832 |
#' @param simplify A [`logical`] scalar: should the results be simplified to a |
|
| 833 |
#' matrix if possible? |
|
| 834 |
#' @param drop A [`logical`] scalar indicating whether to drop unused |
|
| 835 |
#' combinations of grouping values. |
|
| 836 |
#' @param ... Further arguments to be passed to `FUN`. |
|
| 837 |
#' @return A [`matrix`]. |
|
| 838 |
#' @example inst/examples/ex-aggregate.R |
|
| 839 |
#' @author N. Frerebeau |
|
| 840 |
#' @docType methods |
|
| 841 |
#' @family statistics |
|
| 842 |
#' @name aggregate |
|
| 843 |
#' @rdname aggregate |
|
| 844 |
NULL |
|
| 845 | ||
| 846 |
#' Compositional Mean |
|
| 847 |
#' |
|
| 848 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 849 |
#' @inheritParams gmean |
|
| 850 |
#' @param ... Currently not used. |
|
| 851 |
#' @details |
|
| 852 |
#' Closed vector of the columns geometric means. |
|
| 853 |
#' @return A [`numeric`] vector. |
|
| 854 |
#' @references |
|
| 855 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 856 |
#' London: Chapman and Hall, p. 64-91. |
|
| 857 |
#' @example inst/examples/ex-mean.R |
|
| 858 |
#' @author N. Frerebeau |
|
| 859 |
#' @docType methods |
|
| 860 |
#' @family statistics |
|
| 861 |
#' @name mean |
|
| 862 |
#' @rdname mean |
|
| 863 |
NULL |
|
| 864 | ||
| 865 |
#' Sample Quantiles |
|
| 866 |
#' |
|
| 867 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 868 |
#' @param probs A [`numeric`] vector of probabilities with values in \eqn{[0,1]}.
|
|
| 869 |
#' @param na.rm A [`logical`] scalar: should missing values be removed? |
|
| 870 |
#' @param names A [`logical`] scalar: should results be named? |
|
| 871 |
#' @param ... Currently not used. |
|
| 872 |
#' @return A [`numeric`] matrix. |
|
| 873 |
#' @references |
|
| 874 |
#' Filzmoser, P., Hron, K. & Reimann, C. (2009). Univariate Statistical |
|
| 875 |
#' Analysis of Environmental (Compositional) Data: Problems and Possibilities. |
|
| 876 |
#' *Science of The Total Environment*, 407(23): 6100-6108. |
|
| 877 |
#' \doi{10.1016/j.scitotenv.2009.08.008}.
|
|
| 878 |
#' @example inst/examples/ex-mean.R |
|
| 879 |
#' @author N. Frerebeau |
|
| 880 |
#' @docType methods |
|
| 881 |
#' @family statistics |
|
| 882 |
#' @name quantile |
|
| 883 |
#' @rdname quantile |
|
| 884 |
NULL |
|
| 885 | ||
| 886 |
#' Compositional Mean of Data Subsets |
|
| 887 |
#' |
|
| 888 |
#' Splits the data into subsets and computes compositional mean for each. |
|
| 889 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 890 |
#' @param by A `vector` or a list of grouping elements, each as long as the |
|
| 891 |
#' variables in `x` (see [group()]). |
|
| 892 |
#' @inheritParams gmean |
|
| 893 |
#' @param verbose A [`logical`] scalar: should \R report extra information |
|
| 894 |
#' on progress? |
|
| 895 |
#' @param ... Currently not used. |
|
| 896 |
#' @return A [`CompositionMatrix-class`] object. |
|
| 897 |
#' @seealso [mean()], [aggregate()] |
|
| 898 |
#' @example inst/examples/ex-condense.R |
|
| 899 |
#' @author N. Frerebeau |
|
| 900 |
#' @docType methods |
|
| 901 |
#' @family statistics |
|
| 902 |
#' @aliases condense-method |
|
| 903 |
setGeneric( |
|
| 904 |
name = "condense", |
|
| 905 | 8x |
def = function(x, ...) standardGeneric("condense")
|
| 906 |
# valueClass = "CompositionMatrix" |
|
| 907 |
) |
|
| 908 | ||
| 909 |
#' Marginal Compositions |
|
| 910 |
#' |
|
| 911 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 912 |
#' @param parts An [`integer`] or a [`character`] vector specifying the columns |
|
| 913 |
#' to be selected. |
|
| 914 |
#' @param name A [`character`] string giving the name of the amalgamation |
|
| 915 |
#' column. |
|
| 916 |
#' @param ... Currently not used. |
|
| 917 |
#' @return A [`CompositionMatrix-class`] object. |
|
| 918 |
#' @example inst/examples/ex-margin.R |
|
| 919 |
#' @author N. Frerebeau |
|
| 920 |
#' @docType methods |
|
| 921 |
#' @family statistics |
|
| 922 |
#' @aliases margin-method |
|
| 923 |
setGeneric( |
|
| 924 |
name = "margin", |
|
| 925 |
def = function(x, ...) standardGeneric("margin"),
|
|
| 926 |
valueClass = "CompositionMatrix" |
|
| 927 |
) |
|
| 928 | ||
| 929 |
#' Covariance Matrix |
|
| 930 |
#' |
|
| 931 |
#' Computes the (centered) log-ratio covariance matrix (see below). |
|
| 932 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 933 |
#' @param center A [`logical`] scalar: should the *centered* log-ratio |
|
| 934 |
#' covariance matrix be computed? |
|
| 935 |
#' @param method A [`character`] string indicating which covariance is to be |
|
| 936 |
#' computed (see [stats::cov()]). |
|
| 937 |
#' @param ... Currently not used. |
|
| 938 |
#' @return A [`matrix`]. |
|
| 939 |
#' @references |
|
| 940 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 941 |
#' London: Chapman and Hall, p. 64-91. |
|
| 942 |
#' |
|
| 943 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 944 |
#' Boca Raton: CRC Press. |
|
| 945 |
#' @example inst/examples/ex-covariance.R |
|
| 946 |
#' @author N. Frerebeau |
|
| 947 |
#' @docType methods |
|
| 948 |
#' @family statistics |
|
| 949 |
#' @aliases covariance-method |
|
| 950 |
setGeneric( |
|
| 951 |
name = "covariance", |
|
| 952 |
def = function(x, ...) standardGeneric("covariance"),
|
|
| 953 |
valueClass = "matrix" |
|
| 954 |
) |
|
| 955 | ||
| 956 |
#' Log-Ratios Variances |
|
| 957 |
#' |
|
| 958 |
#' Computes log-ratio (weighted) variances. |
|
| 959 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 960 |
#' @param row_weights A [`numeric`] vector of row weights. If `NULL` (the |
|
| 961 |
#' default), equal weights are used. |
|
| 962 |
#' @param column_weights A [`logical`] scalar: should the weights of the |
|
| 963 |
#' log-ratio be used? If `FALSE`, equally-weighted parts are used. |
|
| 964 |
#' Alternatively, a positive [`numeric`] vector of weights can be specified. |
|
| 965 |
#' @param ... Currently not used. |
|
| 966 |
#' @return A [`numeric`] vector of individual variances. |
|
| 967 |
#' @references |
|
| 968 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 969 |
#' Boca Raton: CRC Press. |
|
| 970 |
#' @example inst/examples/ex-variance.R |
|
| 971 |
#' @author N. Frerebeau |
|
| 972 |
#' @docType methods |
|
| 973 |
#' @family statistics |
|
| 974 |
#' @aliases variance-method |
|
| 975 |
setGeneric( |
|
| 976 |
name = "variance", |
|
| 977 |
def = function(x, ...) standardGeneric("variance"),
|
|
| 978 |
valueClass = "numeric" |
|
| 979 |
) |
|
| 980 | ||
| 981 |
#' Total Variance |
|
| 982 |
#' |
|
| 983 |
#' Computes the total (or metric) variance, a global measure of spread. |
|
| 984 |
#' @inheritParams variance |
|
| 985 |
#' @param sd A [`logical`] scalar: should the metric standard deviation be |
|
| 986 |
#' returned instead of the metric variance? |
|
| 987 |
#' @return A [`numeric`] vector. |
|
| 988 |
#' @details |
|
| 989 |
#' Two methods are available, see below. |
|
| 990 |
#' @references |
|
| 991 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 992 |
#' London: Chapman and Hall, p. 64-91. |
|
| 993 |
#' |
|
| 994 |
#' Aitchison, J. (1997). The One-Hour Course in Compositional Data Analysis or |
|
| 995 |
#' Compositional Data Analysis Is Simple. In V. Pawlowsky-Glahn (ed.), |
|
| 996 |
#' *IAMG'97*. Barcelona: International Center for Numerical Methods in |
|
| 997 |
#' Engineering (CIMNE), p. 3-35. |
|
| 998 |
#' |
|
| 999 |
#' Boogaart, K. G. van den & Tolosana-Delgado, R. (2013). *Analyzing |
|
| 1000 |
#' Compositional Data with R*. Berlin Heidelberg: Springer-Verlag. |
|
| 1001 |
#' \doi{10.1007/978-3-642-36809-7}.
|
|
| 1002 |
#' |
|
| 1003 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 1004 |
#' Boca Raton: CRC Press. |
|
| 1005 |
#' |
|
| 1006 |
#' Hron, K. & Kubáček. L. (2011). Statistical Properties of the Total Variation |
|
| 1007 |
#' Estimator for Compositional Data. *Metrika*, 74 (2): 221-230. |
|
| 1008 |
#' \doi{10.1007/s00184-010-0299-3}.
|
|
| 1009 |
#' |
|
| 1010 |
#' Pawlowsky-Glahn, V. & Egozcue, J. J. (2001). Geometric Approach to |
|
| 1011 |
#' Statistical Analysis on the Simplex. *Stochastic Environmental Research and |
|
| 1012 |
#' Risk Assessment*, 15(5): 384-398. \doi{10.1007/s004770100077}.
|
|
| 1013 |
#' @example inst/examples/ex-variance.R |
|
| 1014 |
#' @author N. Frerebeau |
|
| 1015 |
#' @docType methods |
|
| 1016 |
#' @family statistics |
|
| 1017 |
#' @aliases variance_total-method |
|
| 1018 |
setGeneric( |
|
| 1019 |
name = "variance_total", |
|
| 1020 |
def = function(x, ...) standardGeneric("variance_total"),
|
|
| 1021 |
valueClass = "numeric" |
|
| 1022 |
) |
|
| 1023 | ||
| 1024 |
#' Variation Matrix |
|
| 1025 |
#' |
|
| 1026 |
#' Computes the variation matrix (Aitchison 1986, definition 4.4). |
|
| 1027 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 1028 |
#' @param ... Currently not used. |
|
| 1029 |
#' @return A [`matrix`]. |
|
| 1030 |
#' @references |
|
| 1031 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 1032 |
#' London: Chapman and Hall, p. 64-91. |
|
| 1033 |
#' |
|
| 1034 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 1035 |
#' Boca Raton: CRC Press. |
|
| 1036 |
#' @example inst/examples/ex-variation.R |
|
| 1037 |
#' @author N. Frerebeau |
|
| 1038 |
#' @docType methods |
|
| 1039 |
#' @family statistics |
|
| 1040 |
#' @aliases variation-method |
|
| 1041 |
setGeneric( |
|
| 1042 |
name = "variation", |
|
| 1043 |
def = function(x, ...) standardGeneric("variation"),
|
|
| 1044 |
valueClass = "matrix" |
|
| 1045 |
) |
|
| 1046 | ||
| 1047 |
#' Proportionality Index of Parts (PIP) |
|
| 1048 |
#' |
|
| 1049 |
#' Computes an index of association between parts. |
|
| 1050 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 1051 |
#' @param ... Currently not used. |
|
| 1052 |
#' @return A [`matrix`]. |
|
| 1053 |
#' @details |
|
| 1054 |
#' The proportionality index of parts (PIP) is based on the |
|
| 1055 |
#' [variation matrix][variation()], but maintains the range of values whithin |
|
| 1056 |
#' \eqn{(0,1)}.
|
|
| 1057 |
#' @references |
|
| 1058 |
#' Egozcue, J. J.. & Pawlowsky-Glahn, V. (2023). Subcompositional Coherence |
|
| 1059 |
#' and and a Novel Proportionality Index of Parts. *SORT*, 47(2): 229-244. |
|
| 1060 |
#' \doi{10.57645/20.8080.02.7}.
|
|
| 1061 |
#' @example inst/examples/ex-variation.R |
|
| 1062 |
#' @author N. Frerebeau |
|
| 1063 |
#' @docType methods |
|
| 1064 |
#' @family statistics |
|
| 1065 |
#' @aliases pip-method |
|
| 1066 |
setGeneric( |
|
| 1067 |
name = "pip", |
|
| 1068 |
def = function(x, ...) standardGeneric("pip"),
|
|
| 1069 |
valueClass = "matrix" |
|
| 1070 |
) |
|
| 1071 | ||
| 1072 |
# Variation Array |
|
| 1073 |
# |
|
| 1074 |
# Computes the compositional variation array. |
|
| 1075 |
# @param object A [`CompositionMatrix-class`] object. |
|
| 1076 |
# @param ... Currently not used. |
|
| 1077 |
# @return A [`matrix`]. |
|
| 1078 |
# @details |
|
| 1079 |
# The compositional variation array is a square matrix where the upper |
|
| 1080 |
# triangular part displays the pairwise log-ratio variances and the lower |
|
| 1081 |
# triangular part displays the pairwise log-ratio means. |
|
| 1082 |
# @references |
|
| 1083 |
# Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 1084 |
# London: Chapman and Hall, p. 64-91. |
|
| 1085 |
# @example inst/examples/ex-variation_array.R |
|
| 1086 |
# @author N. Frerebeau |
|
| 1087 |
# @docType methods |
|
| 1088 |
# @family statistics |
|
| 1089 |
# @aliases variation_array-method |
|
| 1090 |
# setGeneric( |
|
| 1091 |
# name = "variation_array", |
|
| 1092 |
# def = function(object, ...) standardGeneric("variation_array"),
|
|
| 1093 |
# valueClass = "matrix" |
|
| 1094 |
# ) |
|
| 1095 | ||
| 1096 |
#' Scaling and Centering of Compositional Data |
|
| 1097 |
#' |
|
| 1098 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 1099 |
#' @param center A [`logical`] scalar or a [`numeric`] vector giving the center |
|
| 1100 |
#' to be substracted. |
|
| 1101 |
#' @param scale A [`logical`] scalar or a length-one [`numeric`] vector giving a |
|
| 1102 |
#' scaling factor for multiplication. |
|
| 1103 |
#' @return A [`CompositionMatrix-class`] object. |
|
| 1104 |
#' @references |
|
| 1105 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 1106 |
#' London: Chapman and Hall, p. 64-91. |
|
| 1107 |
#' |
|
| 1108 |
#' Boogaart, K. G. van den & Tolosana-Delgado, R. (2013). *Analyzing |
|
| 1109 |
#' Compositional Data with R*. Berlin Heidelberg: Springer-Verlag. |
|
| 1110 |
#' \doi{10.1007/978-3-642-36809-7}.
|
|
| 1111 |
#' @example inst/examples/ex-scale.R |
|
| 1112 |
#' @author N. Frerebeau |
|
| 1113 |
#' @docType methods |
|
| 1114 |
#' @family statistics |
|
| 1115 |
#' @name scale |
|
| 1116 |
#' @rdname scale |
|
| 1117 |
NULL |
|
| 1118 | ||
| 1119 |
# Distances ==================================================================== |
|
| 1120 |
#' Distances |
|
| 1121 |
#' |
|
| 1122 |
#' Computes the distances between all rows of in `x`. |
|
| 1123 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 1124 |
#' @param method A [`character`] string specifying the distance measure to be |
|
| 1125 |
#' used. See [stats::dist()] for the available distances. |
|
| 1126 |
#' @param diag A [`logical`] scalar indicating whether the diagonal of the |
|
| 1127 |
#' distance matrix should be printed. |
|
| 1128 |
#' @param upper A [`logical`] scalar indicating whether the upper triangle of |
|
| 1129 |
#' the distance matrix should be printed. |
|
| 1130 |
#' @param p An [`integer`] giving the power of the Minkowski distance. |
|
| 1131 |
#' @details |
|
| 1132 |
#' Distances are computed on [CLR-transformed][transform_clr] data. |
|
| 1133 |
#' @return A [`stats::dist`] object. |
|
| 1134 |
#' @references |
|
| 1135 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 1136 |
#' London: Chapman and Hall, p. 64-91. |
|
| 1137 |
#' |
|
| 1138 |
#' Greenacre, M. J. (2019). *Compositional Data Analysis in Practice*. |
|
| 1139 |
#' Boca Raton: CRC Press. |
|
| 1140 |
#' @example inst/examples/ex-dist.R |
|
| 1141 |
#' @seealso [stats::dist()] |
|
| 1142 |
#' @author N. Frerebeau |
|
| 1143 |
#' @docType methods |
|
| 1144 |
#' @family statistics |
|
| 1145 |
#' @name dist |
|
| 1146 |
#' @rdname dist |
|
| 1147 |
NULL |
|
| 1148 | ||
| 1149 |
#' Mahalanobis Distance |
|
| 1150 |
#' |
|
| 1151 |
#' Computes the squared Mahalanobis distance of all rows in `x`. |
|
| 1152 |
#' @param x A [`CompositionMatrix-class`] or an [`ILR-class`] object. |
|
| 1153 |
#' @param center A [`numeric`] vector giving the mean vector of the |
|
| 1154 |
#' distribution. If missing, will be estimated from `x`. |
|
| 1155 |
#' @param cov A [`numeric`] matrix giving the covariance of the |
|
| 1156 |
#' distribution. If missing, will be estimated from `x`. |
|
| 1157 |
#' @param robust A [`logical`] scalar: should robust location and scatter |
|
| 1158 |
#' estimation be used? |
|
| 1159 |
#' @param method A [`character`] string specifying the method to be used. |
|
| 1160 |
#' It must be one of "`mve`" (minimum volume ellipsoid) or "`mcd`" (minimum |
|
| 1161 |
#' covariance determinant). Only used if `robust` is `TRUE`. |
|
| 1162 |
#' @param ... Extra parameters to be passed to [MASS::cov.rob()]. |
|
| 1163 |
#' Only used if `robust` is `TRUE`. |
|
| 1164 |
#' @return A [`numeric`] vector. |
|
| 1165 |
#' @example inst/examples/ex-mahalanobis.R |
|
| 1166 |
#' @seealso [stats::mahalanobis()] |
|
| 1167 |
#' @author N. Frerebeau |
|
| 1168 |
#' @docType methods |
|
| 1169 |
#' @family statistics |
|
| 1170 |
#' @name mahalanobis |
|
| 1171 |
#' @rdname mahalanobis |
|
| 1172 |
NULL |
|
| 1173 | ||
| 1174 |
# Plot ========================================================================= |
|
| 1175 |
## Barplot --------------------------------------------------------------------- |
|
| 1176 |
#' Barplot of Compositional Data |
|
| 1177 |
#' |
|
| 1178 |
#' Displays a compositional bar chart. |
|
| 1179 |
#' @param height A [`CompositionMatrix-class`] object. |
|
| 1180 |
#' @param order_columns A [`logical`] scalar: should should columns be reorderd? |
|
| 1181 |
#' @param order_rows An [`integer`] vector giving the index of the column to be |
|
| 1182 |
#' used for the ordering of the data. |
|
| 1183 |
#' @param decreasing A [`logical`] scalar: should the sort order of rows be |
|
| 1184 |
#' increasing or decreasing? |
|
| 1185 |
#' @param names A [`logical`] scalar: should row names be displayed? |
|
| 1186 |
#' @param space A length-one [`numeric`] vector giving the the amount of space |
|
| 1187 |
#' (as a fraction of the width of a bar) left between each bar |
|
| 1188 |
#' (defaults to \eqn{0.2}).
|
|
| 1189 |
#' @param offset A length-one [`numeric`] vector giving the the amount of space |
|
| 1190 |
#' (as a fraction) left between groups (defaults to \eqn{0.025}). Only used if
|
|
| 1191 |
#' `groups` is not `NULL`. |
|
| 1192 |
#' @param color A (named) vector of colors (will be mapped to the group names |
|
| 1193 |
#' of `object`) or a [`function`] that when called with a single argument (an |
|
| 1194 |
#' integer specifying the number of colors) returns a vector of colors. |
|
| 1195 |
#' @param border The color to draw the borders. |
|
| 1196 |
#' @param axes A [`logical`] scalar: should axes be drawn on the plot? |
|
| 1197 |
#' @param legend A [`logical`] scalar: should the legend be displayed? |
|
| 1198 |
#' @param ... Further graphical parameters. |
|
| 1199 |
#' @return |
|
| 1200 |
#' `barplot()` is called for its side-effects: is results in a graphic being |
|
| 1201 |
#' displayed (invisibly return `height`). |
|
| 1202 |
#' @example inst/examples/ex-barplot.R |
|
| 1203 |
#' @author N. Frerebeau |
|
| 1204 |
#' @docType methods |
|
| 1205 |
#' @family plot methods |
|
| 1206 |
#' @name barplot |
|
| 1207 |
#' @rdname barplot |
|
| 1208 |
NULL |
|
| 1209 | ||
| 1210 |
## Histogram ------------------------------------------------------------------- |
|
| 1211 |
#' Histogram of Compositional Data |
|
| 1212 |
#' |
|
| 1213 |
#' Produces an histogram of univariate ILR data (see Filzmoser *et al.*, 2009). |
|
| 1214 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 1215 |
#' @param select A length-one `vector` of column indices. |
|
| 1216 |
#' @param breaks An object specifying how to compute the breakpoints |
|
| 1217 |
#' (see [graphics::hist()]). |
|
| 1218 |
#' @param freq A [`logical`] scalar: should absolute frequencies (counts) be |
|
| 1219 |
#' displayed? If `FALSE` (the default), relative frequencies (probabilities) |
|
| 1220 |
#' are displayed (see [graphics::hist()]). |
|
| 1221 |
#' @param labels A [`logical`] scalar: should labels be drawn on top of bars? |
|
| 1222 |
#' If `TRUE`, draw the counts or rounded densities; if `labels` is a |
|
| 1223 |
#' `character` vector, draw itself. |
|
| 1224 |
#' @param main A [`character`] string giving a main title for the plot. |
|
| 1225 |
#' @param sub A [`character`] string giving a subtitle for the plot. |
|
| 1226 |
#' @param ann A [`logical`] scalar: should the default annotation (title and x |
|
| 1227 |
#' and y axis labels) appear on the plot? |
|
| 1228 |
#' @param axes A [`logical`] scalar: should axes be drawn on the plot? |
|
| 1229 |
#' @param frame.plot A [`logical`] scalar: should a box be drawn around the |
|
| 1230 |
#' plot? |
|
| 1231 |
#' @param ... Further graphical parameters. |
|
| 1232 |
#' @return |
|
| 1233 |
#' `hist()` is called for its side-effects: is results in a graphic being |
|
| 1234 |
#' displayed (invisibly return `x`). |
|
| 1235 |
#' @references |
|
| 1236 |
#' Filzmoser, P., Hron, K. & Reimann, C. (2009). Univariate Statistical |
|
| 1237 |
#' Analysis of Environmental (Compositional) Data: Problems and Possibilities. |
|
| 1238 |
#' *Science of The Total Environment*, 407(23): 6100-6108. |
|
| 1239 |
#' \doi{10.1016/j.scitotenv.2009.08.008}.
|
|
| 1240 |
#' @example inst/examples/ex-hist.R |
|
| 1241 |
#' @author N. Frerebeau |
|
| 1242 |
#' @docType methods |
|
| 1243 |
#' @family plot methods |
|
| 1244 |
#' @name hist |
|
| 1245 |
#' @rdname hist |
|
| 1246 |
NULL |
|
| 1247 | ||
| 1248 |
## Ternary --------------------------------------------------------------------- |
|
| 1249 |
#' Plot Compositional Data |
|
| 1250 |
#' |
|
| 1251 |
#' Displays a matrix of ternary plots. |
|
| 1252 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 1253 |
#' @param color A (named) vector of colors (will be mapped to the group names |
|
| 1254 |
#' of `object`) or a [`function`] that when called with a single argument (an |
|
| 1255 |
#' integer specifying the number of colors) returns a vector of colors. |
|
| 1256 |
#' @param symbol A (named) vector of colors (will be mapped to the group names |
|
| 1257 |
#' of `object`). |
|
| 1258 |
#' @inheritParams isopleuros::ternary_pairs |
|
| 1259 |
#' @return |
|
| 1260 |
#' `plot()` is called for its side-effects: is results in a graphic being |
|
| 1261 |
#' displayed (invisibly return `x`). |
|
| 1262 |
#' @seealso [isopleuros::ternary_pairs()], [isopleuros::ternary_plot()] |
|
| 1263 |
#' @example inst/examples/ex-pairs.R |
|
| 1264 |
#' @author N. Frerebeau |
|
| 1265 |
#' @docType methods |
|
| 1266 |
#' @family plot methods |
|
| 1267 |
#' @name pairs |
|
| 1268 |
#' @rdname pairs |
|
| 1269 |
NULL |
|
| 1270 | ||
| 1271 |
## Scatter plot ---------------------------------------------------------------- |
|
| 1272 |
#' Plot Log-Ratios |
|
| 1273 |
#' |
|
| 1274 |
#' Displays a scatter plot. |
|
| 1275 |
#' @param x A [`LogRatio-class`] object. |
|
| 1276 |
#' @param jitter_factor,jitter_amount A length-one [`numeric`] vector specifying |
|
| 1277 |
#' the amount of jitter (see [jitter()]). |
|
| 1278 |
#' @param color A (named) vector of colors (will be mapped to the group names |
|
| 1279 |
#' of `object`) or a [`function`] that when called with a single argument (an |
|
| 1280 |
#' integer specifying the number of colors) returns a vector of colors. |
|
| 1281 |
#' @param symbol A (named) vector of colors (will be mapped to the group names |
|
| 1282 |
#' of `object`). |
|
| 1283 |
#' @param xlab,ylab A [`character`] vector giving the x and y axis labels. |
|
| 1284 |
#' @param main A [`character`] string giving a main title for the plot. |
|
| 1285 |
#' @param sub A [`character`] string giving a subtitle for the plot. |
|
| 1286 |
#' @param ann A [`logical`] scalar: should the default annotation (title and x |
|
| 1287 |
#' and y axis labels) appear on the plot? |
|
| 1288 |
#' @param axes A [`logical`] scalar: should axes be drawn on the plot? |
|
| 1289 |
#' @param frame.plot A [`logical`] scalar: should a box be drawn around the |
|
| 1290 |
#' plot? |
|
| 1291 |
#' @param legend A [`list`] of additional arguments to be passed to |
|
| 1292 |
#' [graphics::legend()]; names of the list are used as argument names. |
|
| 1293 |
#' If `NULL`, no legend is displayed. |
|
| 1294 |
#' @param ... Further graphical parameters. |
|
| 1295 |
#' @return |
|
| 1296 |
#' `plot()` is called for its side-effects: is results in a graphic being |
|
| 1297 |
#' displayed (invisibly return `x`). |
|
| 1298 |
#' @example inst/examples/ex-plot.R |
|
| 1299 |
#' @author N. Frerebeau |
|
| 1300 |
#' @docType methods |
|
| 1301 |
#' @family plot methods |
|
| 1302 |
#' @name plot |
|
| 1303 |
#' @rdname plot |
|
| 1304 |
NULL |
|
| 1305 | ||
| 1306 |
## Boxplot --------------------------------------------------------------------- |
|
| 1307 |
#' Boxplot of Log-Ratios |
|
| 1308 |
#' |
|
| 1309 |
#' Displays box-and-whisker plots of the given (grouped) values. |
|
| 1310 |
#' @param x A [`LogRatio-class`] object. |
|
| 1311 |
#' @param range A length-one [`numeric`] vector specifying how far the plot |
|
| 1312 |
#' whiskers extend out from the box (see [graphics::boxplot()]). |
|
| 1313 |
#' @param width A [`numeric`] vector giving the relative widths of the boxes |
|
| 1314 |
#' making up the plot. |
|
| 1315 |
#' @param varwidth A [`logical`] scalar: should the boxes be drawn with widths |
|
| 1316 |
#' proportional to the square-roots of the number of observations in the |
|
| 1317 |
#' groups? |
|
| 1318 |
#' @param notch A [`logical`] scalar: should a notch be drawn in each side of |
|
| 1319 |
#' the boxes? |
|
| 1320 |
#' @param outline A [`logical`] scalar: should the outliers be drawn? |
|
| 1321 |
#' @param plot A [`logical`] scalar: should a boxplot be produced? If `FALSE`, |
|
| 1322 |
#' the summaries which the boxplots are based on are invisibly returned. |
|
| 1323 |
#' @param horizontal A [`logical`] scalar: should the boxplots be horizontal? |
|
| 1324 |
#' @param color A (named) vector of colors (will be mapped to the group names |
|
| 1325 |
#' of `object`) or a [`function`] that when called with a single argument (an |
|
| 1326 |
#' integer specifying the number of colors) returns a vector of colors. |
|
| 1327 |
#' @param xlab,ylab A [`character`] vector giving the x and y axis labels. |
|
| 1328 |
#' @param main A [`character`] string giving a main title for the plot. |
|
| 1329 |
#' @param sub A [`character`] string giving a subtitle for the plot. |
|
| 1330 |
#' @param ann A [`logical`] scalar: should the default annotation (title and x |
|
| 1331 |
#' and y axis labels) appear on the plot? |
|
| 1332 |
#' @param legend A [`list`] of additional arguments to be passed to |
|
| 1333 |
#' [graphics::legend()]; names of the list are used as argument names. |
|
| 1334 |
#' If `NULL`, no legend is displayed. |
|
| 1335 |
#' @param ... Further graphical parameters. |
|
| 1336 |
#' @return |
|
| 1337 |
#' `boxplot()` is called for its side-effects: is results in a graphic being |
|
| 1338 |
#' displayed (invisibly return `x`). |
|
| 1339 |
#' @seealso [graphics::boxplot()] |
|
| 1340 |
#' @example inst/examples/ex-boxplot.R |
|
| 1341 |
#' @author N. Frerebeau |
|
| 1342 |
#' @docType methods |
|
| 1343 |
#' @family plot methods |
|
| 1344 |
#' @name boxplot |
|
| 1345 |
#' @rdname boxplot |
|
| 1346 |
NULL |
|
| 1347 | ||
| 1348 |
## Graph ----------------------------------------------------------------------- |
|
| 1349 |
#' Graph of Log-ratios |
|
| 1350 |
#' |
|
| 1351 |
#' Produces a graph of log-ratios. |
|
| 1352 |
#' @param object A [`LogRatio-class`] object. |
|
| 1353 |
#' @param ... Currently not used. |
|
| 1354 |
#' @return |
|
| 1355 |
#' An \pkg{igraph} graph object.
|
|
| 1356 |
#' @example inst/examples/ex-graph.R |
|
| 1357 |
#' @author N. Frerebeau |
|
| 1358 |
#' @docType methods |
|
| 1359 |
#' @family plot methods |
|
| 1360 |
#' @aliases as_graph-method |
|
| 1361 |
setGeneric( |
|
| 1362 |
name = "as_graph", |
|
| 1363 | ! |
def = function(object, ...) standardGeneric("as_graph")
|
| 1364 |
) |
|
| 1365 | ||
| 1366 |
# Multivariate analysis ======================================================== |
|
| 1367 |
#' Principal Components Analysis |
|
| 1368 |
#' |
|
| 1369 |
#' Computes a principal components analysis based on the singular value |
|
| 1370 |
#' decomposition. |
|
| 1371 |
#' @param object A [`CompositionMatrix-class`] or [`LogRatio-class`] object. |
|
| 1372 |
#' @inheritParams dimensio::pca |
|
| 1373 |
#' @return |
|
| 1374 |
#' A [`dimensio::PCA-class`] object. See [dimensio::pca()] for details. |
|
| 1375 |
#' @references |
|
| 1376 |
#' Aitchison, J. and Greenacre, M. (2002). Biplots of compositional data. |
|
| 1377 |
#' *Journal of the Royal Statistical Society: Series C (Applied Statistics)*, |
|
| 1378 |
#' 51: 375-392. \doi{10.1111/1467-9876.00275}.
|
|
| 1379 |
#' |
|
| 1380 |
#' Filzmoser, P., Hron, K. and Reimann, C. (2009). Principal component analysis |
|
| 1381 |
#' for compositional data with outliers. *Environmetrics*, 20: 621-632. |
|
| 1382 |
#' \doi{10.1002/env.966}.
|
|
| 1383 |
#' @example inst/examples/ex-pca.R |
|
| 1384 |
#' @seealso [dimensio::pca()], [dimensio::biplot()], [dimensio::screeplot()], |
|
| 1385 |
#' [dimensio::viz_individuals()], [dimensio::viz_variables()] |
|
| 1386 |
#' @author N. Frerebeau |
|
| 1387 |
#' @docType methods |
|
| 1388 |
#' @family multivariate analysis |
|
| 1389 |
#' @name pca |
|
| 1390 |
#' @rdname pca |
|
| 1391 |
#' @aliases lra |
|
| 1392 |
NULL |
|
| 1393 | ||
| 1394 |
# Missign Values =============================================================== |
|
| 1395 |
#' Missing Values Policy |
|
| 1396 |
#' |
|
| 1397 |
#' @details |
|
| 1398 |
#' Compositional data are quantitative positive descriptions of the parts |
|
| 1399 |
#' of some whole, carrying relative, rather than absolute, information |
|
| 1400 |
#' (ie. only relative changes are relevant; Aitchison 1986). |
|
| 1401 |
#' |
|
| 1402 |
#' Basically, three situations can be outlined regarding missing values in |
|
| 1403 |
#' compositions: |
|
| 1404 |
#' |
|
| 1405 |
#' * Unobserved quantities. |
|
| 1406 |
#' * Amounts observed, but which happen to be below the detection limit |
|
| 1407 |
#' (thus interpreted as small unknown values). |
|
| 1408 |
#' * Absolutely zero quantities. |
|
| 1409 |
#' |
|
| 1410 |
#' These situations can be represented in several ways: |
|
| 1411 |
#' |
|
| 1412 |
#' * The presence of zeros. |
|
| 1413 |
#' * The presence of missing values (`NA`). |
|
| 1414 |
#' |
|
| 1415 |
#' When creating a [`CompositionMatrix-class`] object, the presence of zero |
|
| 1416 |
#' and [`NA`] values is allowed: this makes it possible to explore and |
|
| 1417 |
#' visualize the data while preserving the missing structure. However, **the |
|
| 1418 |
#' user must deal with these missing values before proceeding further** (e.g. |
|
| 1419 |
#' by removing incomplete cases or replacing the values concerned): log-ratio |
|
| 1420 |
#' transformations cannot be computed in the presence of zeros or missing |
|
| 1421 |
#' values. |
|
| 1422 |
#' @note |
|
| 1423 |
#' If you need more advanced features (e.g. imputation of missing values), |
|
| 1424 |
#' you should consider the \pkg{compositions} or \pkg{robCompositions} package.
|
|
| 1425 |
#' @references |
|
| 1426 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 1427 |
#' London: Chapman and Hall. |
|
| 1428 |
#' @family imputation methods |
|
| 1429 |
#' @name missing |
|
| 1430 |
#' @rdname missing |
|
| 1431 |
NULL |
|
| 1432 | ||
| 1433 |
#' Zero-Replacement |
|
| 1434 |
#' |
|
| 1435 |
#' Multiplicative replacement of zeros. |
|
| 1436 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 1437 |
#' @param value A [`numeric`] vector giving the detection limits of each part |
|
| 1438 |
#' (in \eqn{(0,1)}).
|
|
| 1439 |
#' @param delta A [`numeric`] vector specifying the fraction of the detection |
|
| 1440 |
#' limit to be used in replacement. |
|
| 1441 |
#' @return |
|
| 1442 |
#' An [`CompositionMatrix-class`] object, where all zero values have been |
|
| 1443 |
#' replaced. |
|
| 1444 |
#' @references |
|
| 1445 |
#' Aitchison, J. (1986). *The Statistical Analysis of Compositional Data*. |
|
| 1446 |
#' London: Chapman and Hall. |
|
| 1447 |
#' |
|
| 1448 |
#' Martín-Fernández, J. A., Barceló-Vidal, C. & Pawlowsky-Glahn, V. (2003). |
|
| 1449 |
#' Dealing with Zeros and Missing Values in Compositional Data Sets Using |
|
| 1450 |
#' Nonparametric Imputation. *Mathematical Geology*, 35(3): 253-278. |
|
| 1451 |
#' \doi{10.1023/A:1023866030544}.
|
|
| 1452 |
#' @example inst/examples/ex-zero.R |
|
| 1453 |
#' @author N. Frerebeau |
|
| 1454 |
#' @docType methods |
|
| 1455 |
#' @family imputation methods |
|
| 1456 |
#' @name replace_zero |
|
| 1457 |
#' @rdname replace_zero |
|
| 1458 |
NULL |
|
| 1459 | ||
| 1460 |
#' Missing Values Replacement |
|
| 1461 |
#' |
|
| 1462 |
#' Multiplicative replacement of missing values. |
|
| 1463 |
#' @param x A [`CompositionMatrix-class`] object. |
|
| 1464 |
#' @param value A [`numeric`] vector giving the replacement values. |
|
| 1465 |
#' @return |
|
| 1466 |
#' An [`CompositionMatrix-class`] object, where all missing values have been |
|
| 1467 |
#' replaced. |
|
| 1468 |
#' @references |
|
| 1469 |
#' Martín-Fernández, J. A., Barceló-Vidal, C. & Pawlowsky-Glahn, V. (2003). |
|
| 1470 |
#' Dealing with Zeros and Missing Values in Compositional Data Sets Using |
|
| 1471 |
#' Nonparametric Imputation. *Mathematical Geology*, 35(3): 253-278. |
|
| 1472 |
#' \doi{10.1023/A:1023866030544}.
|
|
| 1473 |
#' @example inst/examples/ex-missing.R |
|
| 1474 |
#' @author N. Frerebeau |
|
| 1475 |
#' @docType methods |
|
| 1476 |
#' @family imputation methods |
|
| 1477 |
#' @name replace_NA |
|
| 1478 |
#' @rdname replace_NA |
|
| 1479 |
NULL |
|
| 1480 | ||
| 1481 |
# Outliers ===================================================================== |
|
| 1482 |
#' Outlier Detection |
|
| 1483 |
#' |
|
| 1484 |
#' @param object A [`CompositionMatrix-class`]. |
|
| 1485 |
#' @param reference A [`CompositionMatrix-class`]. If missing, `object` is used. |
|
| 1486 |
#' @param robust A [`logical`] scalar: should robust estimators be used? |
|
| 1487 |
#' @param method A [`character`] string specifying the method to be used. |
|
| 1488 |
#' It must be one of "`mve`" (minimum volume ellipsoid) or "`mcd`" (minimum |
|
| 1489 |
#' covariance determinant; see [MASS::cov.rob()]). |
|
| 1490 |
#' Only used if `robust` is `TRUE`. |
|
| 1491 |
#' @param quantile A length-one [`numeric`] vector giving the significance level. |
|
| 1492 |
#' `quantile` is used as a cut-off value for outlier detection: observations |
|
| 1493 |
#' with larger (squared) Mahalanobis distance are considered as potential |
|
| 1494 |
#' outliers. |
|
| 1495 |
#' @param ... Further parameters to be passed to [MASS::cov.rob()]. |
|
| 1496 |
#' @details |
|
| 1497 |
#' An outlier can be defined as having a very large Mahalanobis distance from |
|
| 1498 |
#' all observations. In this way, a certain proportion of the observations can |
|
| 1499 |
#' be identified, e.g. the top 2% of values (i.e. values above the 0.98th |
|
| 1500 |
#' percentile of the Chi-2 distribution). |
|
| 1501 |
#' |
|
| 1502 |
#' On the one hand, the Mahalanobis distance is likely to be strongly |
|
| 1503 |
#' affected by the presence of outliers. Rousseeuw and van Zomeren (1990) thus |
|
| 1504 |
#' recommend using robust methods (which are not excessively affected by the |
|
| 1505 |
#' presence of outliers). |
|
| 1506 |
#' |
|
| 1507 |
#' On the other hand, the choice of the threshold for classifying an |
|
| 1508 |
#' observation as an outlier should be discussed. There is no apparent reason |
|
| 1509 |
#' why a particular threshold should be applicable to all data sets |
|
| 1510 |
#' (Filzmoser, Garrett, and Reimann 2005). |
|
| 1511 |
#' @return |
|
| 1512 |
#' * `detect_outlier()` returns an [`OutlierIndex-class`] object. |
|
| 1513 |
#' * `is_outlier()` returns a [`logical`] vector. |
|
| 1514 |
#' @references |
|
| 1515 |
#' Filzmoser, P., Garrett, R. G. & Reimann, C. (2005). Multivariate outlier |
|
| 1516 |
#' detection in exploration geochemistry. *Computers & Geosciences*, |
|
| 1517 |
#' 31(5), 579-587. \doi{10.1016/j.cageo.2004.11.013}.
|
|
| 1518 |
#' |
|
| 1519 |
#' Filzmoser, P. & Hron, K. (2008). Outlier Detection for Compositional Data |
|
| 1520 |
#' Using Robust Methods. *Mathematical Geosciences*, 40(3), 233-248. |
|
| 1521 |
#' \doi{10.1007/s11004-007-9141-5}.
|
|
| 1522 |
#' |
|
| 1523 |
#' Filzmoser, P., Hron, K. & Reimann, C. (2012). Interpretation of multivariate |
|
| 1524 |
#' outliers for compositional data. *Computers & Geosciences*, 39, 77-85. |
|
| 1525 |
#' \doi{10.1016/j.cageo.2011.06.014}.
|
|
| 1526 |
#' |
|
| 1527 |
#' Rousseeuw, P. J. & van Zomeren, B. C. (1990). Unmasking Multivariate Outliers |
|
| 1528 |
#' and Leverage Points. *Journal of the American Statistical Association*, |
|
| 1529 |
#' 85(411): 633-639. \doi{10.1080/01621459.1990.10474920}.
|
|
| 1530 |
#' |
|
| 1531 |
#' Santos, F. (2020). Modern methods for old data: An overview of some robust |
|
| 1532 |
#' methods for outliers detection with applications in osteology. *Journal of |
|
| 1533 |
#' Archaeological Science: Reports*, 32, 102423. |
|
| 1534 |
#' \doi{10.1016/j.jasrep.2020.102423}.
|
|
| 1535 |
#' @example inst/examples/ex-outliers.R |
|
| 1536 |
#' @author N. Frerebeau |
|
| 1537 |
#' @docType methods |
|
| 1538 |
#' @family outlier detection methods |
|
| 1539 |
#' @aliases detect_outlier-method |
|
| 1540 |
setGeneric( |
|
| 1541 |
name = "detect_outlier", |
|
| 1542 | 2x |
def = function(object, reference, ...) standardGeneric("detect_outlier")
|
| 1543 |
) |
|
| 1544 | ||
| 1545 |
#' @rdname detect_outlier |
|
| 1546 |
#' @aliases is_outlier-method |
|
| 1547 |
setGeneric( |
|
| 1548 |
name = "is_outlier", |
|
| 1549 | 1x |
def = function(object, ...) standardGeneric("is_outlier")
|
| 1550 |
) |
|
| 1551 | ||
| 1552 |
#' Plot Outliers |
|
| 1553 |
#' |
|
| 1554 |
#' @param x An [`OutlierIndex-class`] object. |
|
| 1555 |
#' @param type A [`character`] string specifying the type of plot that should be |
|
| 1556 |
#' made. It must be one of "`dotchart`" or "`distance`". |
|
| 1557 |
#' Any unambiguous substring can be given. |
|
| 1558 |
#' @param robust A [`logical`] scalar: should robust Mahalanobis distances be |
|
| 1559 |
#' displayed? Only used if `type` is "`dotchart`". |
|
| 1560 |
#' @param symbols A lenth-three vector of symbol specification for non-outliers |
|
| 1561 |
#' and outliers (resp.). |
|
| 1562 |
#' @param xlim A length-two [`numeric`] vector giving the x limits of the plot. |
|
| 1563 |
#' The default value, `NULL`, indicates that the range of the |
|
| 1564 |
#' [finite][is.finite()] values to be plotted should be used. |
|
| 1565 |
#' @param ylim A length-two [`numeric`] vector giving the y limits of the plot. |
|
| 1566 |
#' The default value, `NULL`, indicates that the range of the |
|
| 1567 |
#' [finite][is.finite()] values to be plotted should be used. |
|
| 1568 |
#' @param xlab,ylab A [`character`] vector giving the x and y axis labels. |
|
| 1569 |
#' @param main A [`character`] string giving a main title for the plot. |
|
| 1570 |
#' @param sub A [`character`] string giving a subtitle for the plot. |
|
| 1571 |
#' @param ann A [`logical`] scalar: should the default annotation (title and x |
|
| 1572 |
#' and y axis labels) appear on the plot? |
|
| 1573 |
#' @param axes A [`logical`] scalar: should axes be drawn on the plot? |
|
| 1574 |
#' @param panel.first An an `expression` to be evaluated after the plot axes are |
|
| 1575 |
#' set up but before any plotting takes place. This can be useful for drawing |
|
| 1576 |
#' background grids. |
|
| 1577 |
#' @param frame.plot A [`logical`] scalar: should a box be drawn around the |
|
| 1578 |
#' plot? |
|
| 1579 |
#' @param panel.last An `expression` to be evaluated after plotting has taken |
|
| 1580 |
#' place but before the axes, title and box are added. |
|
| 1581 |
#' @param legend A [`list`] of additional arguments to be passed to |
|
| 1582 |
#' [graphics::legend()]; names of the list are used as argument names. |
|
| 1583 |
#' If `NULL`, no legend is displayed. |
|
| 1584 |
#' @param ... Further parameters to be passed to [graphics::points()]. |
|
| 1585 |
#' @return |
|
| 1586 |
#' `plot()` is called for its side-effects: is results in a graphic being |
|
| 1587 |
#' displayed (invisibly return `x`). |
|
| 1588 |
#' @references |
|
| 1589 |
#' Filzmoser, P., Garrett, R. G. & Reimann, C. (2005). Multivariate outlier |
|
| 1590 |
#' detection in exploration geochemistry. *Computers & Geosciences*, |
|
| 1591 |
#' 31(5), 579-587. \doi{10.1016/j.cageo.2004.11.013}.
|
|
| 1592 |
#' |
|
| 1593 |
#' Filzmoser, P. & Hron, K. (2008). Outlier Detection for Compositional Data |
|
| 1594 |
#' Using Robust Methods. *Mathematical Geosciences*, 40(3), 233-248. |
|
| 1595 |
#' \doi{10.1007/s11004-007-9141-5}.
|
|
| 1596 |
#' |
|
| 1597 |
#' Filzmoser, P., Hron, K. & Reimann, C. (2012). Interpretation of multivariate |
|
| 1598 |
#' outliers for compositional data. *Computers & Geosciences*, 39, 77-85. |
|
| 1599 |
#' \doi{10.1016/j.cageo.2011.06.014}.
|
|
| 1600 |
#' @example inst/examples/ex-outliers.R |
|
| 1601 |
#' @author N. Frerebeau |
|
| 1602 |
#' @docType methods |
|
| 1603 |
#' @family outlier detection methods |
|
| 1604 |
#' @name plot_outlier |
|
| 1605 |
#' @rdname plot_outlier |
|
| 1606 |
NULL |
|
| 1607 | ||
| 1608 |
# Sourcing ===================================================================== |
|
| 1609 |
#' Mixed-Mode Analysis |
|
| 1610 |
#' |
|
| 1611 |
#' Mixes chemical and petrographic matrices. |
|
| 1612 |
#' @param x A [`matrix`] of chemical compositional data or a |
|
| 1613 |
#' [dissimilarity matrix][stats::dist] for these chemical compositional data. |
|
| 1614 |
#' @param y A [`matrix`] of coded mineralogical binary data or a |
|
| 1615 |
#' [dissimilarity matrix][stats::dist] for these mineralogical data. |
|
| 1616 |
#' @param lambda A length-one [`numeric`] vector giving a weighting factor. |
|
| 1617 |
#' @param mu A length-one [`numeric`] vector that lies between 0 and 1 giving |
|
| 1618 |
#' the mixing parameter. |
|
| 1619 |
#' @param ... Extra parameters to be passed to [cluster::daisy()]. |
|
| 1620 |
#' @return |
|
| 1621 |
#' A [stats::dist] object. |
|
| 1622 |
#' @references |
|
| 1623 |
#' Baxter, M. J., Beardah, C. C., Papageorgiou, I., Cau, M. A., Day, P. M. & |
|
| 1624 |
#' Kilikoglou, V. (2008). On Statistical Approaches to the Study of Ceramic |
|
| 1625 |
#' Artefacts Using Geochemical and Petrographic Data. *Archaeometry*, 50(1): |
|
| 1626 |
#' 142-157. \doi{10.1111/j.1475-4754.2007.00359.x}.
|
|
| 1627 |
#' |
|
| 1628 |
#' Beardah, C. C., Baxter, M. J., Papageorgiou, I. & Cau, M. A. (2003). |
|
| 1629 |
#' "Mixed-Mode" Approaches to the Grouping of Ceramic Artefacts Using S-Plus. |
|
| 1630 |
#' In M. Doerr and A. Sarris, *The Digital Heritage of Archaeology*, p. 261-266. |
|
| 1631 |
#' Athens: Archive of Monuments and Publications, Hellenic Ministry of Culture. |
|
| 1632 |
#' |
|
| 1633 |
#' Gower, J. C. (1971). A general coefficient of similarity and some of its |
|
| 1634 |
#' properties. *Biometrics*, 27(4):857-874. \doi{10.2307/2528823}.
|
|
| 1635 |
#' @note |
|
| 1636 |
#' **Experimental.** |
|
| 1637 |
#' @example inst/examples/ex-mix.R |
|
| 1638 |
#' @author N. Frerebeau |
|
| 1639 |
#' @docType methods |
|
| 1640 |
#' @family sourcing methods |
|
| 1641 |
#' @aliases mix-method |
|
| 1642 |
setGeneric( |
|
| 1643 |
name = "mix", |
|
| 1644 |
def = function(x, y, ...) standardGeneric("mix"),
|
|
| 1645 |
valueClass = "dist" |
|
| 1646 |
) |
| 1 |
# VARIATION MATRIX |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Variation matrix ============================================================= |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname variation |
|
| 8 |
#' @aliases variation,CompositionMatrix-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "variation", |
|
| 11 |
signature = c(x = "CompositionMatrix"), |
|
| 12 |
definition = function(x) {
|
|
| 13 | 2x |
J <- ncol(x) |
| 14 | 2x |
parts <- colnames(x) |
| 15 | ||
| 16 | 2x |
varia <- utils::combn( |
| 17 | 2x |
x = seq_len(J), |
| 18 | 2x |
m = 2, |
| 19 | 2x |
FUN = function(i, coda) {
|
| 20 | 20x |
r <- coda[, i[[1]], drop = TRUE] / coda[, i[[2]], drop = TRUE] |
| 21 | 20x |
z <- log(r, base = exp(1)) |
| 22 | 20x |
stats::var(z) |
| 23 |
}, |
|
| 24 | 2x |
coda = x |
| 25 |
) |
|
| 26 | ||
| 27 | 2x |
mtx <- matrix(data = 0, nrow = J, ncol = J) |
| 28 | 2x |
mtx[lower.tri(mtx, diag = FALSE)] <- varia |
| 29 | 2x |
mtx <- t(mtx) |
| 30 | 2x |
mtx[lower.tri(mtx, diag = FALSE)] <- varia |
| 31 | ||
| 32 | 2x |
dimnames(mtx) <- list(parts, parts) |
| 33 | 2x |
mtx |
| 34 |
} |
|
| 35 |
) |
|
| 36 | ||
| 37 |
#' @export |
|
| 38 |
#' @rdname pip |
|
| 39 |
#' @aliases pip,CompositionMatrix-method |
|
| 40 |
setMethod( |
|
| 41 |
f = "pip", |
|
| 42 |
signature = c(x = "CompositionMatrix"), |
|
| 43 |
definition = function(x) {
|
|
| 44 | 1x |
v <- variation(x) |
| 45 | 1x |
1 / (1 + sqrt(v)) |
| 46 |
} |
|
| 47 |
) |
|
| 48 | ||
| 49 |
# Variation array ============================================================== |
|
| 50 |
# @export |
|
| 51 |
# @rdname variation_array |
|
| 52 |
# @aliases variation_array,CompositionMatrix-method |
|
| 53 |
# setMethod( |
|
| 54 |
# f = "variation_array", |
|
| 55 |
# signature = c(object = "CompositionMatrix"), |
|
| 56 |
# definition = function(object) {
|
|
| 57 |
# J <- ncol(object) |
|
| 58 |
# cbn <- utils::combn(seq_len(J), 2) |
|
| 59 |
# varia <- apply( |
|
| 60 |
# X = cbn, |
|
| 61 |
# MARGIN = 2, |
|
| 62 |
# FUN = function(j, x) {
|
|
| 63 |
# mean(log(x[, j[1]] / x[, j[2]])) |
|
| 64 |
# }, |
|
| 65 |
# x = object |
|
| 66 |
# ) |
|
| 67 |
# |
|
| 68 |
# mtx <- variation(object) |
|
| 69 |
# mtx[lower.tri(mtx, diag = FALSE)] <- varia |
|
| 70 |
# mtx |
|
| 71 |
# } |
|
| 72 |
# ) |
| 1 |
# DISTANCES |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Distances ==================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @method dist CompositionMatrix |
|
| 8 |
dist.CompositionMatrix <- function(x, method = "euclidean", |
|
| 9 |
diag = FALSE, upper = FALSE, p = 2) {
|
|
| 10 | 2x |
x <- transform_clr(x) |
| 11 | 2x |
stats::dist(x, method = method, diag = diag, upper = upper, p = p) |
| 12 |
} |
|
| 13 | ||
| 14 |
#' @export |
|
| 15 |
#' @rdname dist |
|
| 16 |
#' @aliases dist,CompositionMatrix-method |
|
| 17 |
setMethod("dist", "CompositionMatrix", dist.CompositionMatrix)
|
|
| 18 | ||
| 19 |
# Mahalanobis ================================================================== |
|
| 20 |
#' @export |
|
| 21 |
#' @method mahalanobis CompositionMatrix |
|
| 22 |
mahalanobis.CompositionMatrix <- function(x, center, cov, ..., robust = TRUE, |
|
| 23 |
method = c("mve", "mcd")) {
|
|
| 24 |
## Transformation |
|
| 25 | 1x |
x <- transform_ilr(x) |
| 26 | 1x |
mahalanobis(x, center, cov, ..., robust = robust, method = method) |
| 27 |
} |
|
| 28 | ||
| 29 |
#' @export |
|
| 30 |
#' @rdname mahalanobis |
|
| 31 |
#' @aliases mahalanobis,CompositionMatrix-method |
|
| 32 |
setMethod("mahalanobis", "CompositionMatrix", mahalanobis.CompositionMatrix)
|
|
| 33 | ||
| 34 |
#' @export |
|
| 35 |
#' @method mahalanobis ILR |
|
| 36 |
mahalanobis.ILR <- function(x, center, cov, ..., robust = TRUE, |
|
| 37 |
method = c("mve", "mcd")) {
|
|
| 38 | ||
| 39 | 1x |
if (missingORnull(center) | missingORnull(cov)) {
|
| 40 | 1x |
if (!robust) method <- "classical" # Standard estimators |
| 41 | ! |
else method <- match.arg(method, several.ok = FALSE) # Robust estimators |
| 42 | 1x |
v <- MASS::cov.rob(x, method = method, ...) |
| 43 |
} |
|
| 44 | ||
| 45 | 1x |
est <- list(center = NULL, cov = NULL) |
| 46 | 1x |
est$center <- if (missingORnull(center)) v$center else center |
| 47 | 1x |
est$cov <- if (missingORnull(cov)) v$cov else cov |
| 48 | ||
| 49 | 1x |
message(v$sing) |
| 50 | ||
| 51 | 1x |
stats::mahalanobis(x, center = est$center, cov = est$cov) |
| 52 |
} |
|
| 53 | ||
| 54 |
#' @export |
|
| 55 |
#' @rdname mahalanobis |
|
| 56 |
#' @aliases mahalanobis,ILR-method |
|
| 57 |
setMethod("mahalanobis", "ILR", mahalanobis.ILR)
|
| 1 |
# MIXED-MODE ANALYSIS |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# First approach =============================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @describeIn mix First approach of mixed-mode analysis. |
|
| 8 |
#' @aliases mix,matrix,matrix-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "mix", |
|
| 11 |
signature = c(x = "matrix", y = "matrix"), |
|
| 12 |
definition = function(x, y, lambda = 1, ...) {
|
|
| 13 |
## Validation |
|
| 14 | ! |
arkhe::assert_package("cluster")
|
| 15 | ! |
stopifnot(nrow(y) == nrow(x)) |
| 16 | ||
| 17 | ! |
X <- vector(mode = "list", length = lambda + 1) |
| 18 | ! |
X[[1]] <- y |
| 19 | ! |
lambda <- as.integer(lambda[[1L]]) |
| 20 | ! |
for (i in seq_len(lambda)) X[[i + 1]] <- x |
| 21 | ! |
X <- do.call(cbind, X) |
| 22 | ||
| 23 | ! |
d <- cluster::daisy(X, metric = "gower", ...) |
| 24 | ! |
as.dist(as.matrix(d)) |
| 25 |
} |
|
| 26 |
) |
|
| 27 | ||
| 28 |
# Second approach ============================================================== |
|
| 29 |
#' @export |
|
| 30 |
#' @describeIn mix Second approach of mixed-mode analysis. |
|
| 31 |
#' @aliases mix,dist,dist-method |
|
| 32 |
setMethod( |
|
| 33 |
f = "mix", |
|
| 34 |
signature = c(x = "dist", y = "dist"), |
|
| 35 |
definition = function(x, y, mu = 0.5) {
|
|
| 36 |
## Validation |
|
| 37 | ! |
stopifnot(mu >= 0 & mu <= 1) |
| 38 | ||
| 39 | ! |
x <- as.matrix(x) |
| 40 | ! |
y <- as.matrix(y) |
| 41 | ||
| 42 | ! |
d <- mu * x + (1 - mu) * y |
| 43 | ! |
as.dist(d) |
| 44 |
} |
|
| 45 |
) |
| 1 |
# COMPOSITIONAL MEAN |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @rdname condense |
|
| 7 |
#' @aliases condense,CompositionMatrix-method |
|
| 8 |
setMethod( |
|
| 9 |
f = "condense", |
|
| 10 |
signature = "CompositionMatrix", |
|
| 11 |
definition = function(x, by, ignore_na = FALSE, ignore_zero = TRUE, |
|
| 12 |
verbose = FALSE, ...) {
|
|
| 13 | 3x |
x <- group(x, by = by, verbose = verbose) |
| 14 | 3x |
y <- methods::callGeneric(x = x, ignore_na = ignore_na, |
| 15 | 3x |
ignore_zero = ignore_zero, verbose = verbose, ...) |
| 16 | 3x |
ungroup(y) |
| 17 |
} |
|
| 18 |
) |
|
| 19 | ||
| 20 |
#' @export |
|
| 21 |
#' @rdname condense |
|
| 22 |
#' @aliases condense,GroupedComposition-method |
|
| 23 |
setMethod( |
|
| 24 |
f = "condense", |
|
| 25 |
signature = "GroupedComposition", |
|
| 26 |
definition = function(x, by = NULL, ignore_na = FALSE, ignore_zero = TRUE, |
|
| 27 |
verbose = FALSE, ...) {
|
|
| 28 |
## Grouping |
|
| 29 | 5x |
grp <- group_factor(x, exclude = NULL) |
| 30 | 1x |
if (!is.null(by)) x <- group(x, by = by, verbose = verbose) |
| 31 | ||
| 32 |
## Compute mean |
|
| 33 | 5x |
z <- aggregate( |
| 34 | 5x |
x = x, |
| 35 | 5x |
FUN = mean, |
| 36 | 5x |
ignore_na = ignore_na, |
| 37 | 5x |
ignore_zero = ignore_zero, |
| 38 | 5x |
simplify = TRUE |
| 39 |
) |
|
| 40 | 5x |
tot <- tapply( |
| 41 | 5x |
X = totals(x), |
| 42 | 5x |
INDEX = group_factor(x, exclude = NULL), |
| 43 | 5x |
FUN = mean |
| 44 |
) |
|
| 45 | ||
| 46 | 5x |
z <- .CompositionMatrix(z, totals = as.numeric(tot)) |
| 47 | 5x |
group(z, by = flatten_chr(x = grp, by = group_factor(x, exclude = NULL)), |
| 48 | 5x |
verbose = verbose) |
| 49 |
} |
|
| 50 |
) |
|
| 51 | ||
| 52 |
flatten_chr <- function(x, by) {
|
|
| 53 | 5x |
x <- as.character(x) |
| 54 | 5x |
z <- tapply(X = x, INDEX = by, FUN = unique, simplify = FALSE) |
| 55 | 5x |
z <- vapply(X = z, FUN = paste0, FUN.VALUE = character(1), collapse = ":") |
| 56 | 5x |
z |
| 57 |
} |
| 1 |
# CHEMISTRY |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
is_chemical <- function(object) {
|
|
| 6 | 6x |
pattern <- "^([A-Z]{1}[a-z]?[1-9]*)+$"
|
| 7 | 6x |
z <- grepl(pattern, x = object) |
| 8 | 6x |
names(z) <- object |
| 9 | 6x |
z |
| 10 |
} |
|
| 11 | ||
| 12 |
#' @export |
|
| 13 |
#' @rdname chemistry |
|
| 14 |
#' @aliases is_oxide,character-method |
|
| 15 |
setMethod( |
|
| 16 |
f = "is_oxide", |
|
| 17 |
signature = c(object = "character"), |
|
| 18 |
definition = function(object) {
|
|
| 19 | 3x |
pattern <- "^[A-Z]{1}[a-z]?[1-9]*[O]{1}[1-9]*$"
|
| 20 | 3x |
z <- grepl(pattern, x = object) |
| 21 | 3x |
names(z) <- object |
| 22 | 3x |
z |
| 23 |
} |
|
| 24 |
) |
|
| 25 | ||
| 26 |
#' @export |
|
| 27 |
#' @rdname chemistry |
|
| 28 |
#' @aliases is_oxide,CompositionMatrix-method |
|
| 29 |
setMethod( |
|
| 30 |
f = "is_oxide", |
|
| 31 |
signature = c(object = "CompositionMatrix"), |
|
| 32 |
definition = function(object) {
|
|
| 33 | ! |
methods::callGeneric(colnames(object)) |
| 34 |
} |
|
| 35 |
) |
|
| 36 | ||
| 37 |
#' @export |
|
| 38 |
#' @rdname chemistry |
|
| 39 |
#' @aliases is_element_major,CompositionMatrix-method |
|
| 40 |
setMethod( |
|
| 41 |
f = "is_element_major", |
|
| 42 |
signature = c(object = "CompositionMatrix"), |
|
| 43 |
definition = function(object, min = 1 / 100, max = Inf) {
|
|
| 44 | 1x |
.element_threshold(object, min = min, max = max) |
| 45 |
} |
|
| 46 |
) |
|
| 47 | ||
| 48 |
#' @export |
|
| 49 |
#' @rdname chemistry |
|
| 50 |
#' @aliases is_element_minor,CompositionMatrix-method |
|
| 51 |
setMethod( |
|
| 52 |
f = "is_element_minor", |
|
| 53 |
signature = c(object = "CompositionMatrix"), |
|
| 54 |
definition = function(object, min = 0.1 / 100, max = 1 / 100) {
|
|
| 55 | 1x |
.element_threshold(object, min = min, max = max) |
| 56 |
} |
|
| 57 |
) |
|
| 58 | ||
| 59 |
#' @export |
|
| 60 |
#' @rdname chemistry |
|
| 61 |
#' @aliases is_element_trace,CompositionMatrix-method |
|
| 62 |
setMethod( |
|
| 63 |
f = "is_element_trace", |
|
| 64 |
signature = c(object = "CompositionMatrix"), |
|
| 65 |
definition = function(object, min = -Inf, max = 0.1 / 100) {
|
|
| 66 | ! |
.element_threshold(object, min = min, max = max) |
| 67 |
} |
|
| 68 |
) |
|
| 69 | ||
| 70 |
.element_threshold <- function(x, min = -Inf, max = Inf) {
|
|
| 71 | 2x |
x <- mean(x) |
| 72 | 2x |
x >= min & x < max |
| 73 |
} |
| 1 |
# DATA TRANSFORMATION: ADDITIVE LOG RATIO |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# ALR ========================================================================== |
|
| 6 |
alr_base <- function(D) {
|
|
| 7 | 11x |
V <- diag(1, nrow = D, ncol = D - 1) |
| 8 | 11x |
V[D, ] <- -1 |
| 9 | ||
| 10 | 11x |
V |
| 11 |
} |
|
| 12 | ||
| 13 |
#' @export |
|
| 14 |
#' @rdname transform_alr |
|
| 15 |
#' @aliases transform_alr,CompositionMatrix-method |
|
| 16 |
setMethod( |
|
| 17 |
f = "transform_alr", |
|
| 18 |
signature = c(object = "CompositionMatrix"), |
|
| 19 |
definition = function(object, j = ncol(object), weights = FALSE) {
|
|
| 20 | 9x |
D <- ncol(object) |
| 21 | 9x |
parts <- colnames(object) |
| 22 | ||
| 23 |
## Reorder (move denominator) |
|
| 24 | 9x |
j <- if (is.character(j)) which(parts == j) else as.integer(j) |
| 25 | 9x |
ordering <- c(which(j != seq_len(D)), j) |
| 26 | 9x |
parts <- parts[ordering] |
| 27 | 9x |
z <- object[, ordering, drop = FALSE] |
| 28 | ||
| 29 |
## Compute ratios |
|
| 30 | 9x |
base <- alr_base(D) |
| 31 | 9x |
alr <- log(z, base = exp(1)) %*% base |
| 32 | 9x |
rownames(alr) <- rownames(object) |
| 33 | 9x |
colnames(alr) <- paste(parts[-D], parts[D], sep = "_") |
| 34 | ||
| 35 |
## Compute weights |
|
| 36 | 9x |
weights <- make_weights(object, weights = weights) |
| 37 | ||
| 38 | 9x |
.ALR( |
| 39 | 9x |
alr, |
| 40 | 9x |
parts = parts, |
| 41 | 9x |
ratio = paste(parts[-D], parts[D], sep = "/"), |
| 42 | 9x |
order = order(ordering), |
| 43 | 9x |
base = base, |
| 44 | 9x |
weights = weights, |
| 45 | 9x |
totals = totals(object) |
| 46 |
) |
|
| 47 |
} |
|
| 48 |
) |
|
| 49 | ||
| 50 |
#' @export |
|
| 51 |
#' @rdname transform_alr |
|
| 52 |
#' @aliases transform_alr,GroupedComposition-method |
|
| 53 |
setMethod( |
|
| 54 |
f = "transform_alr", |
|
| 55 |
signature = c(object = "GroupedComposition"), |
|
| 56 |
definition = function(object, j = ncol(object), weights = FALSE) {
|
|
| 57 | ! |
z <- methods::callNextMethod() |
| 58 | ! |
.GroupedALR(z, group_indices = group_indices(object), |
| 59 | ! |
group_levels = group_levels(object), |
| 60 | ! |
group_ordered = is_ordered(object)) |
| 61 |
} |
|
| 62 |
) |
|
| 63 | ||
| 64 |
#' @export |
|
| 65 |
#' @rdname transform_alr |
|
| 66 |
#' @aliases transform_alr,CLR-method |
|
| 67 |
setMethod( |
|
| 68 |
f = "transform_alr", |
|
| 69 |
signature = c(object = "CLR"), |
|
| 70 |
definition = function(object, j = ncol(object)) {
|
|
| 71 | 2x |
D <- ncol(object) |
| 72 | 2x |
parts <- object@parts |
| 73 | ||
| 74 |
## Reorder (move denominator) |
|
| 75 | 2x |
j <- if (is.character(j)) which(parts == j) else as.integer(j) |
| 76 | 2x |
ordering <- c(which(j != seq_len(D)), j) |
| 77 | 2x |
parts <- parts[ordering] |
| 78 | 2x |
z <- object[, ordering, drop = FALSE] |
| 79 | ||
| 80 |
## Compute ratios |
|
| 81 | 2x |
base <- alr_base(D) |
| 82 | 2x |
alr <- z %*% base |
| 83 | 2x |
rownames(alr) <- rownames(object) |
| 84 | 2x |
colnames(alr) <- paste(parts[-D], parts[D], sep = "_") |
| 85 | ||
| 86 | 2x |
.ALR( |
| 87 | 2x |
alr, |
| 88 | 2x |
parts = parts, |
| 89 | 2x |
ratio = paste(parts[-D], parts[D], sep = "/"), |
| 90 | 2x |
order = order(ordering), |
| 91 | 2x |
base = base, |
| 92 | 2x |
weights = object@weights, |
| 93 | 2x |
totals = totals(object) |
| 94 |
) |
|
| 95 |
} |
|
| 96 |
) |
|
| 97 | ||
| 98 |
#' @export |
|
| 99 |
#' @rdname transform_alr |
|
| 100 |
#' @aliases transform_alr,GroupedCLR-method |
|
| 101 |
setMethod( |
|
| 102 |
f = "transform_alr", |
|
| 103 |
signature = c(object = "GroupedCLR"), |
|
| 104 |
definition = function(object, j = ncol(object), weights = FALSE) {
|
|
| 105 | ! |
z <- methods::callNextMethod() |
| 106 | ! |
.GroupedALR(z, group_indices = group_indices(object), |
| 107 | ! |
group_levels = group_levels(object), |
| 108 | ! |
group_ordered = is_ordered(object)) |
| 109 |
} |
|
| 110 |
) |
| 1 |
# MARGIN |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Margin ======================================================================= |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname margin |
|
| 8 |
#' @aliases margin,CompositionMatrix-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "margin", |
|
| 11 |
signature = c("CompositionMatrix"),
|
|
| 12 |
definition = function(x, parts = c(1, 2), name = "*") {
|
|
| 13 |
## Validation |
|
| 14 | 1x |
p <- NCOL(x) |
| 15 | 1x |
parts <- unique(parts) |
| 16 | 1x |
if (is.character(parts)) parts <- match(parts, colnames(x)) |
| 17 | ! |
if (p <= length(parts)) return(x) |
| 18 | 1x |
if (p == length(parts) + 1) {
|
| 19 | ! |
d <- seq_len(p) |
| 20 | ! |
d <- c(d[parts], d[-parts]) |
| 21 | ! |
return(x[, d, drop = FALSE]) |
| 22 |
} |
|
| 23 | ||
| 24 | 1x |
rest <- x[, -parts, drop = FALSE] |
| 25 | 1x |
star <- apply(X = rest, MARGIN = 1, FUN = gmean) |
| 26 | 1x |
mar <- cbind(x[, parts, drop = FALSE], star) |
| 27 | 1x |
colnames(mar) <- c(colnames(x)[parts], name[[1L]]) |
| 28 | ||
| 29 | 1x |
clo <- closure(mar) |
| 30 | 1x |
methods::initialize(x, clo) |
| 31 |
} |
|
| 32 |
) |
| 1 |
# STATISTICS: MEAN |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Mean ========================================================================= |
|
| 6 |
#' @export |
|
| 7 |
#' @method mean CompositionMatrix |
|
| 8 |
mean.CompositionMatrix <- function(x, ..., ignore_na = FALSE, ignore_zero = TRUE) {
|
|
| 9 | 35x |
m <- apply( |
| 10 | 35x |
X = x, |
| 11 | 35x |
MARGIN = 2, |
| 12 | 35x |
FUN = gmean, |
| 13 | 35x |
ignore_na = ignore_na, |
| 14 | 35x |
ignore_zero = ignore_zero, |
| 15 | 35x |
simplify = TRUE |
| 16 |
) |
|
| 17 | 35x |
m <- closure(m) |
| 18 | 35x |
names(m) <- colnames(x) |
| 19 | 35x |
m |
| 20 |
} |
|
| 21 | ||
| 22 |
#' @export |
|
| 23 |
#' @rdname mean |
|
| 24 |
#' @aliases mean,CompositionMatrix-method |
|
| 25 |
setMethod("mean", "CompositionMatrix", mean.CompositionMatrix)
|
|
| 26 | ||
| 27 |
#' Geometric Mean |
|
| 28 |
#' |
|
| 29 |
#' @param x A [`numeric`] vector. |
|
| 30 |
#' @param trim A length-one [`numeric`] vector specifying the fraction (0 to 0.5) |
|
| 31 |
#' of observations to be trimmed from each end of `x` before the mean is |
|
| 32 |
#' computed. |
|
| 33 |
#' @param ignore_na A [`logical`] scalar: should [missing values][NA] be |
|
| 34 |
#' stripped before the computation proceeds? |
|
| 35 |
#' @param ignore_zero A [`logical`] scalar: should zeros be stripped before the |
|
| 36 |
#' computation proceeds? |
|
| 37 |
#' @return A [`numeric`] vector. |
|
| 38 |
#' @keywords internal |
|
| 39 |
gmean <- function(x, trim = 0, ignore_na = FALSE, ignore_zero = TRUE) {
|
|
| 40 | 10x |
if (ignore_na) x <- x[is.finite(x)] |
| 41 | 235x |
if (ignore_zero) x <- x[x > 0] |
| 42 | 237x |
exp(mean(log(unclass(x)), trim = trim)) |
| 43 |
} |
| 1 |
# DATA TRANSFORMATION: LOG RATIO |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# LR =========================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname transform_lr |
|
| 8 |
#' @aliases transform_lr,CompositionMatrix-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "transform_lr", |
|
| 11 |
signature = c(object = "CompositionMatrix"), |
|
| 12 |
definition = function(object, weights = FALSE) {
|
|
| 13 | 5x |
J <- ncol(object) |
| 14 | 5x |
parts <- colnames(object) |
| 15 | ||
| 16 |
## Compute weights |
|
| 17 | 5x |
weights <- make_weights(object, weights = weights) |
| 18 | ||
| 19 |
## Computes ratios |
|
| 20 | 5x |
jj <- utils::combn(seq_len(J), 2, simplify = FALSE) |
| 21 | 5x |
lr <- matrix(data = 0, nrow = nrow(object), ncol = length(jj)) |
| 22 | 5x |
for (i in seq_along(jj)) {
|
| 23 | 36x |
a <- jj[[i]][[1]] |
| 24 | 36x |
b <- jj[[i]][[2]] |
| 25 | 36x |
r <- object[, a, drop = TRUE] / object[, b, drop = TRUE] |
| 26 | 36x |
lr[, i] <- log(r, base = exp(1)) |
| 27 |
} |
|
| 28 | ||
| 29 |
## Make names |
|
| 30 | 5x |
ratio <- unlist(utils::combn(parts, 2, FUN = paste, collapse = "/", simplify = FALSE)) |
| 31 | 5x |
rownames(lr) <- rownames(object) |
| 32 | 5x |
colnames(lr) <- ratio |
| 33 | ||
| 34 | 5x |
.LR( |
| 35 | 5x |
lr, |
| 36 | 5x |
parts = parts, |
| 37 | 5x |
ratio = ratio, |
| 38 | 5x |
order = seq_len(J), |
| 39 | 5x |
weights = weights, |
| 40 | 5x |
totals = totals(object) |
| 41 |
) |
|
| 42 |
} |
|
| 43 |
) |
|
| 44 | ||
| 45 |
#' @export |
|
| 46 |
#' @rdname transform_lr |
|
| 47 |
#' @aliases transform_lr,GroupedComposition-method |
|
| 48 |
setMethod( |
|
| 49 |
f = "transform_lr", |
|
| 50 |
signature = c(object = "GroupedComposition"), |
|
| 51 |
definition = function(object, weights = FALSE) {
|
|
| 52 | ! |
z <- methods::callNextMethod() |
| 53 | ! |
.GroupedLR(z, group_indices = group_indices(object), |
| 54 | ! |
group_levels = group_levels(object), |
| 55 | ! |
group_ordered = is_ordered(object)) |
| 56 |
} |
|
| 57 |
) |
| 1 |
# BIND |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @rdname bind |
|
| 7 |
#' @aliases rbind2,CompositionMatrix,CompositionMatrix-method |
|
| 8 |
setMethod( |
|
| 9 |
f = "rbind2", |
|
| 10 |
signature = c(x = "CompositionMatrix", y = "CompositionMatrix"), |
|
| 11 |
definition = function(x, y) {
|
|
| 12 | 4x |
arkhe::assert_colnames(y, colnames(x)) |
| 13 | ||
| 14 | 4x |
mtx_x <- methods::as(x, "matrix") |
| 15 | 4x |
mtx_y <- methods::as(y, "matrix") |
| 16 | ||
| 17 | 4x |
spl <- c(rownames(x), rownames(y)) |
| 18 | 4x |
if (any(duplicated(spl))) {
|
| 19 | ! |
warning(tr_("Duplicated rownames!"), call. = FALSE)
|
| 20 | ! |
spl <- make.unique(spl, sep = "_") |
| 21 |
} |
|
| 22 | ||
| 23 | 4x |
z <- rbind(mtx_x, mtx_y) |
| 24 | 4x |
rownames(z) <- spl |
| 25 | 4x |
.CompositionMatrix(z, totals = c(totals(x), totals(y))) |
| 26 |
} |
|
| 27 |
) |
|
| 28 | ||
| 29 |
#' @export |
|
| 30 |
#' @rdname bind |
|
| 31 |
#' @aliases rbind2,GroupedComposition,GroupedComposition-method |
|
| 32 |
setMethod( |
|
| 33 |
f = "rbind2", |
|
| 34 |
signature = c(x = "GroupedComposition", y = "GroupedComposition"), |
|
| 35 |
definition = function(x, y) {
|
|
| 36 | ! |
z <- methods::callNextMethod(x, y) |
| 37 | ! |
group(z, by = c(group_names(x), group_names(y))) |
| 38 |
} |
|
| 39 |
) |
| 1 |
# PAIRS |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# CompositionMatrix ============================================================ |
|
| 6 |
#' @export |
|
| 7 |
#' @method pairs CompositionMatrix |
|
| 8 |
pairs.CompositionMatrix <- function(x, margin = NULL, ...) {
|
|
| 9 | 1x |
isopleuros::ternary_pairs(x, margin = margin, ...) |
| 10 | 1x |
invisible(x) |
| 11 |
} |
|
| 12 | ||
| 13 |
#' @export |
|
| 14 |
#' @rdname pairs |
|
| 15 |
#' @aliases pairs,CompositionMatrix-method |
|
| 16 |
setMethod("pairs", c(x = "CompositionMatrix"), pairs.CompositionMatrix)
|
|
| 17 | ||
| 18 |
#' @export |
|
| 19 |
#' @method pairs GroupedComposition |
|
| 20 |
pairs.GroupedComposition <- function(x, ..., margin = NULL, |
|
| 21 |
color = NULL, symbol = NULL) {
|
|
| 22 |
## Aesthetics |
|
| 23 | 1x |
lvl <- group_names(x) |
| 24 | 1x |
col <- khroma::palette_color_discrete(color)(lvl) |
| 25 | 1x |
pch <- khroma::palette_shape(symbol)(lvl) |
| 26 | ||
| 27 | 1x |
isopleuros::ternary_pairs(x, margin = margin, col = col, pch = pch, ...) |
| 28 | 1x |
invisible(x) |
| 29 |
} |
|
| 30 | ||
| 31 |
#' @export |
|
| 32 |
#' @rdname pairs |
|
| 33 |
#' @aliases pairs,GroupedComposition-method |
|
| 34 |
setMethod("pairs", c(x = "GroupedComposition"), pairs.GroupedComposition)
|
| 1 |
# SPLIT |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @method split CompositionMatrix |
|
| 7 |
split.CompositionMatrix <- function(x, f, drop = FALSE, ...) {
|
|
| 8 | ! |
lapply( |
| 9 | ! |
X = split(x = seq_len(nrow(x)), f = f, drop = drop, sep = "_", ...), |
| 10 | ! |
FUN = function(ind) x[ind, , drop = FALSE] |
| 11 |
) |
|
| 12 |
} |
|
| 13 | ||
| 14 |
#' @export |
|
| 15 |
#' @rdname group_split |
|
| 16 |
#' @aliases split,CompositionMatrix-method |
|
| 17 |
setMethod("split", "CompositionMatrix", split.CompositionMatrix)
|
|
| 18 | ||
| 19 |
#' @export |
|
| 20 |
#' @method split LogRatio |
|
| 21 |
split.LogRatio <- function(x, f, drop = FALSE, ...) {
|
|
| 22 | ! |
lapply( |
| 23 | ! |
X = split(x = seq_len(nrow(x)), f = f, drop = drop, sep = "_", ...), |
| 24 | ! |
FUN = function(ind) x[ind, , drop = FALSE] |
| 25 |
) |
|
| 26 |
} |
|
| 27 | ||
| 28 |
#' @export |
|
| 29 |
#' @rdname group_split |
|
| 30 |
#' @aliases split,LogRatio-method |
|
| 31 |
setMethod("split", "LogRatio", split.LogRatio)
|
|
| 32 | ||
| 33 |
#' @export |
|
| 34 |
#' @rdname group_split |
|
| 35 |
#' @aliases group_split,GroupedComposition-method |
|
| 36 |
setMethod( |
|
| 37 |
f = "group_split", |
|
| 38 |
signature = "GroupedComposition", |
|
| 39 |
definition = function(object, ...) {
|
|
| 40 | 6x |
lapply( |
| 41 | 6x |
X = group_rows(object), |
| 42 | 6x |
FUN = function(ind) ungroup(object[ind, , drop = FALSE]) |
| 43 |
) |
|
| 44 |
} |
|
| 45 |
) |
|
| 46 | ||
| 47 |
#' @export |
|
| 48 |
#' @rdname group_split |
|
| 49 |
#' @aliases group_split,GroupedLogRatio-method |
|
| 50 |
setMethod( |
|
| 51 |
f = "group_split", |
|
| 52 |
signature = "GroupedLogRatio", |
|
| 53 |
definition = function(object, ...) {
|
|
| 54 | ! |
lapply( |
| 55 | ! |
X = group_rows(object), |
| 56 | ! |
FUN = function(ind) ungroup(object[ind, , drop = FALSE]) |
| 57 |
) |
|
| 58 |
} |
|
| 59 |
) |
| 1 |
# PCA |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
#' @export |
|
| 6 |
#' @describeIn pca PCA of centered log-ratio, i.e. log-ratio analysis (LRA). |
|
| 7 |
#' @aliases pca,CompositionMatrix-method |
|
| 8 |
setMethod( |
|
| 9 |
f = "pca", |
|
| 10 |
signature = c("CompositionMatrix"),
|
|
| 11 |
definition = function(object, center = TRUE, scale = FALSE, rank = NULL, |
|
| 12 |
sup_row = NULL, sup_col = NULL, |
|
| 13 |
weight_row = NULL, weight_col = NULL) {
|
|
| 14 | 1x |
message(tr_("PCA of centered log-ratio (CLR)."))
|
| 15 | 1x |
x <- transform_clr(object) |
| 16 | 1x |
methods::callGeneric(object = x, center = center, scale = scale, |
| 17 | 1x |
rank = rank, sup_row = sup_row, sup_col = sup_col, |
| 18 | 1x |
weight_row = weight_row, weight_col = weight_col) |
| 19 |
} |
|
| 20 |
) |
|
| 21 | ||
| 22 |
#' @export |
|
| 23 |
#' @rdname pca |
|
| 24 |
#' @aliases pca,LogRatio-method |
|
| 25 |
setMethod( |
|
| 26 |
f = "pca", |
|
| 27 |
signature = c("LogRatio"),
|
|
| 28 |
definition = function(object, center = TRUE, scale = FALSE, rank = NULL, |
|
| 29 |
sup_row = NULL, sup_col = NULL, |
|
| 30 |
weight_row = NULL, weight_col = NULL) {
|
|
| 31 | 1x |
methods::callNextMethod(object, center = center, scale = scale, |
| 32 | 1x |
rank = rank, sup_row = sup_row, |
| 33 | 1x |
sup_col = sup_col, weight_row = weight_row, |
| 34 | 1x |
weight_col = weight_col) |
| 35 |
} |
|
| 36 |
) |
| 1 |
# COVARIANCE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Covariance =================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @rdname covariance |
|
| 8 |
#' @aliases covariance,CompositionMatrix-method |
|
| 9 |
setMethod( |
|
| 10 |
f = "covariance", |
|
| 11 |
signature = c(x = "CompositionMatrix"), |
|
| 12 |
definition = function(x, center = TRUE, method = "pearson") {
|
|
| 13 | 6x |
x <- if (center) transform_clr(x) else transform_alr(x) |
| 14 | 6x |
methods::callGeneric(x = x, method = method) |
| 15 |
} |
|
| 16 |
) |
|
| 17 | ||
| 18 |
#' @export |
|
| 19 |
#' @describeIn covariance Computes the log-ratio covariance matrix |
|
| 20 |
#' (Aitchison 1986, definition 4.5). |
|
| 21 |
#' @aliases covariance,ALR-method |
|
| 22 |
setMethod( |
|
| 23 |
f = "covariance", |
|
| 24 |
signature = c(x = "ALR"), |
|
| 25 |
definition = function(x, method = "pearson") {
|
|
| 26 | 1x |
stats::cov(x, method = method) |
| 27 |
} |
|
| 28 |
) |
|
| 29 | ||
| 30 |
#' @export |
|
| 31 |
#' @describeIn covariance Computes the centered log-ratio covariance matrix |
|
| 32 |
#' (Aitchison 1986, definition 4.6). |
|
| 33 |
#' @aliases covariance,ALR-method |
|
| 34 |
setMethod( |
|
| 35 |
f = "covariance", |
|
| 36 |
signature = c(x = "CLR"), |
|
| 37 |
definition = function(x, method = "pearson") {
|
|
| 38 | 5x |
stats::cov(x, method = method) |
| 39 |
} |
|
| 40 |
) |
| 1 |
# STATISTICS: QUANTILE |
|
| 2 |
#' @include AllGenerics.R |
|
| 3 |
NULL |
|
| 4 | ||
| 5 |
# Quantile ===================================================================== |
|
| 6 |
#' @export |
|
| 7 |
#' @method quantile CompositionMatrix |
|
| 8 |
quantile.CompositionMatrix <- function(x, ..., probs = seq(0, 1, 0.25), |
|
| 9 |
na.rm = FALSE, names = TRUE) {
|
|
| 10 | 1x |
apply( |
| 11 | 1x |
X = x, |
| 12 | 1x |
MARGIN = 2, |
| 13 | 1x |
FUN = stats::quantile, |
| 14 | 1x |
probs = probs, |
| 15 | 1x |
na.rm = na.rm, |
| 16 | 1x |
names = names, |
| 17 |
... |
|
| 18 |
) |
|
| 19 |
} |
|
| 20 | ||
| 21 |
#' @export |
|
| 22 |
#' @rdname quantile |
|
| 23 |
#' @aliases quantile,CompositionMatrix-method |
|
| 24 |
setMethod("quantile", "CompositionMatrix", quantile.CompositionMatrix)
|