Это то, что я в конечном итоге использовал. Спасибо @Joris за помощь!
Моя x
матрица довольно большая. Предполагая, что это размер n * p
, n=200k
и p=10k
в моем случае.
Хитрость заключается в том, чтобы поддерживать разреженность операций и выполнять вычисления на p * p
матрицах вместо p*n x n*p
.
Версия 1 более проста, но менее эффективна по времени и памяти, поскольку операция с внешним продуктом стоит дорого:
sparse.cor2 <- function(x){
n <- nrow(x)
covmat <- (crossprod(x)-2*(colMeans(x) %o% colSums(x))
+n*colMeans(x)%o%colMeans(x))/(n-1)
sdvec <- sqrt(diag(covmat)) # standard deviations of columns
covmat/crossprod(t(sdvec)) # correlation matrix
}
Версия 2 более эффективна по времени (экономит несколько операций) и по памяти. Все еще требует огромного количества памяти для матрицы p=10k
:
sparse.cor3 <- function(x){
memory.limit(size=10000)
n <- nrow(x)
cMeans <- colMeans(x)
cSums <- colSums(x)
# Calculate the population covariance matrix.
# There's no need to divide by (n-1) as the std. dev is also calculated the same way.
# The code is optimized to minize use of memory and expensive operations
covmat <- tcrossprod(cMeans, (-2*cSums+n*cMeans))
crossp <- as.matrix(crossprod(x))
covmat <- covmat+crossp
sdvec <- sqrt(diag(covmat)) # standard deviations of columns
covmat/crossprod(t(sdvec)) # correlation matrix
}
Сравнение времени (sparse.cor - последняя версия @Joris):
> X <- sample(0:10,1e7,replace=T,p=c(0.9,rep(0.01,10)))
> x <- Matrix(X,ncol=10)
>
> object.size(x)
11999472 bytes
>
> system.time(corx <- sparse.cor(x))
user system elapsed
0.50 0.06 0.56
> system.time(corx2 <- sparse.cor2(x))
user system elapsed
0.17 0.00 0.17
> system.time(corx3 <- sparse.cor3(x))
user system elapsed
0.13 0.00 0.12
> system.time(correg <-cor(as.matrix(x)))
user system elapsed
0.25 0.03 0.29
> all.equal(c(as.matrix(corx)),c(as.matrix(correg)))
[1] TRUE
> all.equal(c(as.matrix(corx2)),c(as.matrix(correg)))
[1] TRUE
> all.equal(c(as.matrix(corx3)),c(as.matrix(correg)))
[1] TRUE
намного больше x
матрица:
> X <- sample(0:10,1e8,replace=T,p=c(0.9,rep(0.01,10)))
> x <- Matrix(X,ncol=10)
> object.size(x)
120005688 bytes
> system.time(corx2 <- sparse.cor2(x))
user system elapsed
1.47 0.07 1.53
> system.time(corx3 <- sparse.cor3(x))
user system elapsed
1.18 0.09 1.29
> system.time(corx <- sparse.cor(x))
user system elapsed
5.43 1.26 6.71