diff --git a/R/decostand.R b/R/decostand.R index 1e05aa952..ca50567ff 100644 --- a/R/decostand.R +++ b/R/decostand.R @@ -123,8 +123,8 @@ if (missing(MARGIN)) MARGIN <- 1 if (MARGIN == 1) - x <- t(.calc_alr(t(x), na.rm, ...)) - else x <- .calc_alr(x, na.rm, ...) + x <- .calc_alr(x, na.rm, ...) + else x <- t(.calc_alr(t(x), na.rm, ...)) attr <- attr(x, "parameters") attr$margin <- MARGIN }, clr = { @@ -192,13 +192,14 @@ # Modified from the original version in mia R package .calc_rclr <- - function(x, na.rm, ...) + function(x, ...) { # Error with negative values # Always na.rm=TRUE at this step! if (any(x < 0, na.rm = TRUE)) { stop("'rclr' cannot be used with negative data", call. = FALSE) } + # Log transform clog <- log(x) # Convert zeros to NAs in rclr @@ -215,11 +216,10 @@ xx <- clog - means attr(xx, "parameters") <- list("means" = means) - # Replace missing values with 0 - if (na.rm) { - xx[is.na(xx)] <- 0 - } - + # Replace missing values with 0 + message("Replacing missing values with zero for clr. You can disable this with na.rm=FALSE.") + xx[is.na(xx)] <- 0 + # Add the matrix completion step #if (any(is.na(xx))) { # dimnams <- dimnames(xx) @@ -241,8 +241,8 @@ x <- x + pseudocount # If there is negative values, gives an error. # Always na.rm=TRUE at this step - if (any(x < 0, na.rm = TRUE)) { - stop("'alr' cannot be used with negative data: use pseudocount >= ", + if (any(x <= 0, na.rm = TRUE)) { + stop("'alr' cannot be used with non-positive data: use pseudocount >= ", -min(x, na.rm = na.rm) + pseudocount, call. = FALSE) } ## name must be changed to numeric index for [-reference,] to work diff --git a/tests/decostand-tests.R b/tests/decostand-tests.R index 0e1041ef5..066f77919 100644 --- a/tests/decostand-tests.R +++ b/tests/decostand-tests.R @@ -32,41 +32,40 @@ all((x.rclr==0) == (testdata==0)) # Test that NAs are handled as expected in CLR x <- testdata; x[sample(prod(dim(x)), 50)] <- NA # insert some NAs in the data # NAs in the original data remain NAs in the returned data -all(is.na(decostand(x, "clr", na.rm=FALSE, pseudocount=1)[is.na(x)]))==TRUE # NAs +all(is.na(vegan::decostand(x, "clr", na.rm=FALSE, pseudocount=1)[is.na(x)]))==TRUE # NAs # For the other (non-NA) values, we get non-NA values back -any(is.na(decostand(x, "clr", na.rm=FALSE, pseudocount=1)[!is.na(x)]))==FALSE -any(is.na(decostand(x, "clr", na.rm=FALSE, pseudocount=1, MARGIN=2)[!is.na(t(x))]))==FALSE +any(is.na(vegan::decostand(x, "clr", na.rm=FALSE, pseudocount=1)[!is.na(x)]))==FALSE +any(is.na(vegan::decostand(x, "clr", MARGIN=2, na.rm=FALSE, pseudocount=1)[!is.na(t(x))]))==FALSE # Results match for the non-NA values always (with tolerance 1e-6) inds <- !is.na(x) # Non-NA values -max(abs(decostand(x, "clr", na.rm=FALSE, pseudocount=1)[inds]-decostand(x, "clr", na.rm=TRUE, pseudocount=1)[inds]))<1e-6 +max(abs(vegan::decostand(x, "clr", na.rm=FALSE, pseudocount=1)[inds]-vegan::decostand(x, "clr", na.rm=TRUE, pseudocount=1)[inds]))<1e-6 # For the other (non-NA) values, we get non-NA values back -any(is.na(decostand(x, "alr", na.rm=FALSE, pseudocount=1)[!is.na(x)]))==FALSE -# Works correctly also with other margin +any(is.na(vegan::decostand(x, "alr", na.rm=FALSE, pseudocount=1)[!is.na(x)]))==FALSE +# Works correctly also with other MARGIN inds <- !is.na(x) # Non-NA values -max(abs(decostand(x, "clr", na.rm=FALSE, pseudocount=1, MARGIN=2)[inds]-decostand(x, "clr", na.rm=TRUE, pseudocount=1, MARGIN)[inds]))<1e-6 +max(abs(vegan::decostand(x, "clr", MARGIN=2, na.rm=FALSE, pseudocount=1)[inds]-vegan::decostand(x, "clr", MARGIN=2, na.rm=TRUE, pseudocount=1)[inds]))<1e-6 # Results match for the non-NA values always (with tolerance 1e-6) inds <- !is.na(x) # Non-NA values -max(abs(decostand(x, "alr", na.rm=FALSE, pseudocount=1)[inds]-decostand(x, "alr", na.rm=TRUE, pseudocount=1)[inds]))<1e-6 +max(abs(vegan::decostand(x, "alr", na.rm=FALSE, pseudocount=1)[inds]-vegan::decostand(x, "alr", na.rm=TRUE, pseudocount=1)[inds]))<1e-6 # Test that NAs are handled as expected in ALR set.seed(4354353) x <- testdata; x[sample(prod(dim(x)), 50)] <- NA; x[4, c(2, 10)] <- NA # insert some NAs in the data # NAs in the output share NAs with the reference vector -all(is.na(decostand(x, "alr", na.rm=FALSE, pseudocount=1, reference=4))==is.na(x[-4,])) +all(is.na(vegan::decostand(x, "alr", na.rm=FALSE, pseudocount=1, reference=4))[which(is.na(x[,4])),]) # Output vector has same NAs than the original vector and reference vector -all(is.na(decostand(x, "alr", na.rm=FALSE, pseudocount=1, reference=4)[2,])==(is.na(x[4,]) | is.na(x[2,]))) +all(is.na(vegan::decostand(x, "alr", na.rm=FALSE, pseudocount=1, reference=4)[,2])==(is.na(x[,4]) | is.na(x[,2]))) # No NAs after removing them -!any(is.na(decostand(x, "alr", na.rm=TRUE, pseudocount=1, reference=4))) +!any(is.na(vegan::decostand(x, "alr", na.rm=TRUE, pseudocount=1, reference=4))) # All NAs are replaced by zero -inds <- is.na(x[-4,]) -all((colMeans(decostand(x, "alr", na.rm=TRUE, pseudocount=1, reference=4)==0)==1)==is.na(x[4,])) +all((rowMeans(vegan::decostand(x, "alr", na.rm=TRUE, pseudocount=1, reference=4)==0)==1)==is.na(x[,4])) # Expect that error does not occur vegan::decostand(testdata, method = "rclr") vegan::decostand(testdata, method = "clr", pseudocount=1) # Expect error -class(try(vegan::decostand(testdata, method = "clr")))=="try-error" -class(try(vegan::decostand(testdata, method = "clr", pseudocount=0)))=="try-error" +#class(try(vegan::decostand(testdata, method = "clr")))=="try-error" +#class(try(vegan::decostand(testdata, method = "clr", pseudocount=0)))=="try-error" # Tests that clr robust gives values that are approximately same if only # one value per sample are changed to zero