Agregaré una respuesta más visual a su pregunta, mediante el uso de una comparación de modelo nulo. El procedimiento baraja aleatoriamente los datos en cada columna para preservar la varianza general mientras se pierde la covarianza entre variables (columnas). Esto se realiza varias veces y la distribución resultante de valores singulares en la matriz aleatoria se compara con los valores originales.
Yo uso en prcomp
lugar de svd
para la descomposición de la matriz, pero los resultados son similares:
set.seed(1)
m <- matrix(runif(10000,min=0,max=25), nrow=100,ncol=100)
S <- svd(scale(m, center = TRUE, scale=FALSE))
P <- prcomp(m, center = TRUE, scale=FALSE)
plot(S$d, P$sdev) # linearly related
La comparación del modelo nulo se realiza en la matriz centrada a continuación:
library(sinkr) # https://github.com/marchtaylor/sinkr
# centred data
Pnull <- prcompNull(m, center = TRUE, scale=FALSE, nperm = 100)
Pnull$n.sig
boxplot(Pnull$Lambda[,1:20], ylim=range(Pnull$Lambda[,1:20], Pnull$Lambda.orig[1:20]), outline=FALSE, col=8, border="grey50", log="y", main=paste("m (center=FALSE); n sig. =", Pnull$n.sig))
lines(apply(Pnull$Lambda, 2, FUN=quantile, probs=0.95))
points(Pnull$Lambda.orig[1:20], pch=16)
El siguiente es un diagrama de caja de la matriz permutada con el cuantil del 95% de cada valor singular que se muestra como la línea continua. Los valores originales de PCA de m
son los puntos. todo lo cual se encuentra debajo de la línea del 95%. Por lo tanto, su amplitud es indistinguible del ruido aleatorio.
Se puede realizar el mismo procedimiento en la versión no centrada de m
con el mismo resultado. Sin valores singulares significativos:
# centred data
Pnull <- prcompNull(m, center = FALSE, scale=FALSE, nperm = 100)
Pnull$n.sig
boxplot(Pnull$Lambda[,1:20], ylim=range(Pnull$Lambda[,1:20], Pnull$Lambda.orig[1:20]), outline=FALSE, col=8, border="grey50", log="y", main=paste("m (center=TRUE); n sig. =", Pnull$n.sig))
lines(apply(Pnull$Lambda, 2, FUN=quantile, probs=0.95))
points(Pnull$Lambda.orig[1:20], pch=16)
A modo de comparación, veamos un conjunto de datos con un conjunto de datos no aleatorio: iris
# iris dataset example
m <- iris[,1:4]
Pnull <- prcompNull(m, center = TRUE, scale=FALSE, nperm = 100)
Pnull$n.sig
boxplot(Pnull$Lambda, ylim=range(Pnull$Lambda, Pnull$Lambda.orig), outline=FALSE, col=8, border="grey50", log="y", main=paste("m (center=FALSE); n sig. =", Pnull$n.sig))
lines(apply(Pnull$Lambda, 2, FUN=quantile, probs=0.95))
points(Pnull$Lambda.orig[1:20], pch=16)
Aquí, el primer valor singular es significativo y explica más del 92% de la varianza total:
P <- prcomp(m, center = TRUE)
P$sdev^2 / sum(P$sdev^2)
# [1] 0.924618723 0.053066483 0.017102610 0.005212184