superponer - Reemplazar NA''s en cada columna de la matriz con la mediana de esa columna
superponer graficas en r (4)
Posiblemente data.frame
llegar más fácilmente a través de la conversión a data.frame
y volver a la matrix
como resultado, usando vapply
:
vapply(as.data.frame(mat1), function(x)
replace(x, is.na(x), median(x,na.rm=TRUE)), FUN.VALUE=numeric(nrow(mat1))
)
Estoy tratando de reemplazar los NA en cada columna de una matriz con la mediana de esa columna, sin embargo, cuando trato de usar lapply
o sapply
me sale un error; el código funciona cuando uso un for-loop y cuando cambio una columna a la vez, ¿qué estoy haciendo mal?
Ejemplo:
set.seed(1928)
mat <- matrix(rnorm(100*110), ncol = 110)
mat[sample(1:length(mat), 700, replace = FALSE)] <- NA
mat1 <- mat2 <- mat
mat1 <- lapply(mat1,
function(n) {
mat1[is.na(mat1[,n]),n] <- median(mat1[,n], na.rm = TRUE)
}
)
for (n in 1:ncol(mat2)) {
mat2[is.na(mat2[,n]),n] <- median(mat2[,n], na.rm = TRUE)
}
Sugiero vectorizar esto usando el paquete matrixStats
lugar de calcular una mediana por columna usando cualquiera de los bucles ( sapply
también es un bucle en el sentido de que evalúa una función en cada iteración).
Primero, crearemos un índice de NA
indx <- which(is.na(mat), arr.ind = TRUE)
Luego, reemplace las NA
usando las medianas de columna precalculadas y de acuerdo con el índice
mat[indx] <- matrixStats::colMedians(mat, na.rm = TRUE)[indx[, 2]]
lapply
sobre una lista. ¿Quieres pasar por las columnas?
matx <- sapply(seq_len(ncol(mat1)), function(n) {
mat1[is.na(mat1[,n]),n] <- median(mat1[,n], na.rm = TRUE)
})
aunque básicamente se trata de hacer lo que hace el ejemplo de bucle (pero presumiblemente más rápido).
Puedes usar sweep
:
sweep(mat, MARGIN = 2,
STATS = apply(mat, 2, median, na.rm=TRUE),
FUN = function(x,s) ifelse(is.na(x), s, x)
)
EDITAR: También puede STATS=matrixStats::colMedians(mat, na.rm=TRUE)
para obtener un poco más de rendimiento.