Skip to content

Commit bc75512

Browse files
committed
optspace does not double-recentre output, but decostand does
Initial centring is not a part of optspace (and never done there), so the final centring should neither be that the method should return approximation of the input. However, double-centring is done in decostand. With this the output of optspace changes, but the output of decostand ("rclr") and vegdist ("robust.aitchison") remain unchanged.
1 parent c066757 commit bc75512

File tree

5 files changed

+26
-26
lines changed

5 files changed

+26
-26
lines changed

R/decostand.R

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@
221221
if (impute && any(is.na(xx))) {
222222
xx <- optspace(xx, ropt = ropt, niter = niter, tol = tol,
223223
verbose = verbose)$M
224+
## Centring is common operation supporting output visualization
225+
## Centre cols to 0
226+
xx <- as.matrix(scale(xx, center = TRUE, scale = FALSE))
227+
## Centre rows to 0
228+
xx <- as.matrix(t(scale(t(xx), center = TRUE, scale = FALSE)))
224229
}
225230
xx
226231
}

R/optspace.R

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,6 @@
144144
# Reconstruct the matrix
145145
M <- X %*% S %*% t(Y)
146146

147-
# Centering is common operation supporting output visualization
148-
# Center cols to 0
149-
M <- as.matrix(scale(M, center = TRUE, scale = FALSE))
150-
# Center rows to 0
151-
M <- as.matrix(t(scale(t(M), center = TRUE, scale = FALSE)))
152-
153147
dimnames(M) <- dimnames(x)
154148
# Add imputed matrix to the output
155149
out$M <- M

man/optspace.Rd

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,17 @@ This implementation removes the trimming step of the original
3737
\code{Roptspace::OptSpace} code in order to leave feature filtering to the
3838
user. Some of the defaults have been adjusted to better reflect
3939
ecological data. The implementation has been adjusted for ecological
40-
applications as in Martino et al. (2019). The imputed matrix (M) in
41-
the optspace output includes matrix reconstruction (XSY'), with
42-
subsequent centering for the columns and rows.
40+
applications as in Martino et al. (2019). The imputed matrix (\eqn{M}) in
41+
the optspace output includes matrix reconstruction (\eqn{XSY'}).
4342
}
4443

4544
\value{Returns a named list containing:
4645
\item{X}{an \eqn{(n \times r)}{(n x r)} matrix as left singular vectors.}
4746
\item{S}{an \eqn{(r \times r)}{(r x r)} matrix as singular values.}
4847
\item{Y}{an \eqn{(m \times r)}{(m x r)} matrix as right singular vectors.}
4948
\item{dist}{a vector containing reconstruction errors at each successive iteration.}
50-
\item{M}{an \eqn{(n \times m)}{(n x m)} imputed matrix, with columns and rows centered to zero.}
49+
\item{M}{an \eqn{(n \times m)}{(n x m)} imputed matrix as calculated
50+
from \code{X}, \code{S} and \code{Y}.}
5151
}
5252

5353
\author{Leo Lahti and Cameron Martino, with adaptations of the method

tests/decostand-tests.R

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ x[sample(prod(dim(x)), 50)] <- NA # insert some NAs in the data
3838
all(is.na(decostand(x, "clr", na.rm = FALSE, pseudocount = 1)[is.na(x)])) == TRUE # NAs
3939
# For the other (non-NA) values, we get non-NA values back
4040
any(is.na(decostand(x, "clr", na.rm = FALSE, pseudocount = 1)[!is.na(x)])) == FALSE
41-
any(is.na(decostand(x, "clr", MARGIN = 2, na.rm = FALSE, pseudocount = 1)[!is.na(x)])) == FALSE
41+
any(is.na(decostand(x, "clr", MARGIN = 2, na.rm = FALSE, pseudocount = 1)[!is.na(x)])) == FALSE
4242
# Results match for the non-NA values always (with tolerance 1e-6)
4343
inds <- !is.na(x) # Non-NA values
4444
max(abs(decostand(x, "clr", na.rm = FALSE, pseudocount = 1)[inds] -
@@ -76,7 +76,7 @@ decostand(testdata, method = "clr", pseudocount = 1)
7676
#class(try(decostand(testdata, method = "clr"))) == "try-error"
7777
#class(try(decostand(testdata, method = "clr", pseudocount = 0))) == "try-error"
7878

79-
# Tests that clr robust gives values that are approximately same if only
79+
# Tests that clr robust gives values that are approximately same if only
8080
# one value per sample are changed to zero
8181
# Adds pseudocount
8282
test <- testdata + 1
@@ -103,9 +103,8 @@ x2 <- decostand(varespec, method = "rclr", impute = FALSE)
103103

104104
# Matrix completion
105105
x2c <- optspace(x2, ropt = 3, niter = 5, tol = 1e-5, verbose = FALSE)$M
106-
all(as.matrix(x1) == as.matrix(x2c))
107-
108-
x2c <- optspace(x2, niter = 5, tol = 1e-5, verbose = FALSE)$M
106+
x2c <- scale(x2c, center = TRUE, scale = FALSE)
107+
x2c <- t(scale(t(x2c), center = TRUE, scale = FALSE))
109108
all(as.matrix(x1) == as.matrix(x2c))
110109

111110
############################# NAMES ####################################

tests/decostand-tests.Rout.save

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Type 'q()' to quit R.
6060
> # For the other (non-NA) values, we get non-NA values back
6161
> any(is.na(decostand(x, "clr", na.rm = FALSE, pseudocount = 1)[!is.na(x)])) == FALSE
6262
[1] TRUE
63-
> any(is.na(decostand(x, "clr", MARGIN = 2, na.rm = FALSE, pseudocount = 1)[!is.na(x)])) == FALSE
63+
> any(is.na(decostand(x, "clr", MARGIN = 2, na.rm = FALSE, pseudocount = 1)[!is.na(x)])) == FALSE
6464
[1] TRUE
6565
> # Results match for the non-NA values always (with tolerance 1e-6)
6666
> inds <- !is.na(x) # Non-NA values
@@ -334,10 +334,14 @@ row18 -0.14885299
334334
row19 0.91755915
335335
row20 0.33766080
336336
attr(,"scaled:center")
337-
[1] -0.0031079619 -0.0463480942 -0.0267762284 0.0089869339 0.0380073003
338-
[6] -0.0216677154 -0.0095070243 -0.0129853877 -0.0151765084 0.0739366224
339-
[11] 0.0813752690 0.0153170116 -0.0001358339 -0.0203385433 -0.0102092705
340-
[16] -0.0133788389 0.0543704488 -0.0876478093 0.0272043261 -0.0319186959
337+
row1 row2 row3 row4 row5
338+
-0.0031079619 -0.0463480942 -0.0267762284 0.0089869339 0.0380073003
339+
row6 row7 row8 row9 row10
340+
-0.0216677154 -0.0095070243 -0.0129853877 -0.0151765084 0.0739366224
341+
row11 row12 row13 row14 row15
342+
0.0813752690 0.0153170116 -0.0001358339 -0.0203385433 -0.0102092705
343+
row16 row17 row18 row19 row20
344+
-0.0133788389 0.0543704488 -0.0876478093 0.0272043261 -0.0319186959
341345
attr(,"decostand")
342346
[1] "rclr"
343347
> decostand(testdata, method = "clr", pseudocount = 1)
@@ -551,7 +555,7 @@ attr(,"decostand")
551555
> #class(try(decostand(testdata, method = "clr"))) == "try-error"
552556
> #class(try(decostand(testdata, method = "clr", pseudocount = 0))) == "try-error"
553557
>
554-
> # Tests that clr robust gives values that are approximately same if only
558+
> # Tests that clr robust gives values that are approximately same if only
555559
> # one value per sample are changed to zero
556560
> # Adds pseudocount
557561
> test <- testdata + 1
@@ -828,10 +832,8 @@ col50 FALSE
828832
>
829833
> # Matrix completion
830834
> x2c <- optspace(x2, ropt = 3, niter = 5, tol = 1e-5, verbose = FALSE)$M
831-
> all(as.matrix(x1) == as.matrix(x2c))
832-
[1] TRUE
833-
>
834-
> x2c <- optspace(x2, niter = 5, tol = 1e-5, verbose = FALSE)$M
835+
> x2c <- scale(x2c, center = TRUE, scale = FALSE)
836+
> x2c <- t(scale(t(x2c), center = TRUE, scale = FALSE))
835837
> all(as.matrix(x1) == as.matrix(x2c))
836838
[1] TRUE
837839
>
@@ -875,4 +877,4 @@ col50 FALSE
875877
>
876878
> proc.time()
877879
user system elapsed
878-
0.438 0.048 0.485
880+
0.436 0.048 0.481

0 commit comments

Comments
 (0)