modify manipulate lists r list null

manipulate - Eliminar elementos NULL de la lista de listas



modify list r (7)

¿Cómo elimino los elementos nulos de una lista de listas, como a continuación, en R?

lll <- list(list(NULL),list(1),list("a"))

El objeto que quiero se vería así:

lll <- list(list(1),list("a"))

Vi una respuesta similar aquí: ¿cómo puedo eliminar un elemento de una lista? pero no fue capaz de extenderlo de listas simples a una lista de listas.

EDITAR

Mal ejemplo anterior por mi parte. Ambas respuestas funcionan en casos más simples (arriba). ¿Qué pasa si la lista es como:

lll <- list(list(NULL),list(1,2,3),list("a","b","c"))

Cómo llegar:

lll <- list(list(1,2,3),list("a","b","c"))


Aquí hay una opción usando la combinación de Filter y Negate

Filter(Negate(function(x) is.null(unlist(x))), lll) # [[1]] # [[1]][[1]] # [1] 1 # # # [[2]] # [[2]][[1]] # [1] "a"


Como tiene listas en listas, probablemente necesite ejecutar l/sapply dos veces, como por ejemplo:

lll[!sapply(lll,sapply,is.null)] #[[1]] #[[1]][[1]] #[1] 1 # # #[[2]] #[[2]][[1]] #[1] "a"


Esta solución recursiva tiene la virtud de trabajar en listas aún más profundamente anidadas.

Está muy inspirado en la respuesta de Gabor Grothendieck a esta pregunta bastante similar . Mi modificación de ese código es necesaria si la función también es eliminar objetos como list(NULL) (no es lo mismo que NULL ), como lo desea.

## A helper function that tests whether an object is either NULL _or_ ## a list of NULLs is.NullOb <- function(x) is.null(x) | all(sapply(x, is.null)) ## Recursively step down into list, removing all such objects rmNullObs <- function(x) { x <- Filter(Negate(is.NullOb), x) lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x) } rmNullObs(lll) # [[1]] # [[1]][[1]] # [1] 1 # # # [[2]] # [[2]][[1]] # [1] "a"

Aquí hay un ejemplo de su aplicación a una lista anidada más profundamente, sobre la cual las otras soluciones actualmente propuestas fallan varias veces.

LLLL <- list(lll) rmNullObs(LLLL) # [[1]] # [[1]][[1]] # [[1]][[1]][[1]] # [[1]][[1]][[1]][[1]] # [1] 1 # # # [[1]][[1]][[2]] # [[1]][[1]][[2]][[1]] # [1] "a"


Hay una nueva lista de paquetes en CRAN, gracias a Kun Ren por hacer nuestra vida más fácil.

list.clean(.data, fun = is.null, recursive = FALSE)

o para la eliminación recursiva de NULL:

list.clean(.data, fun = is.null, recursive = TRUE)


Para este ejemplo en particular, también puede usar unlist con su argumento recursive .

lll[!sapply(unlist(lll, recursive=FALSE), is.null)] # [[1]] # [[1]][[1]] # [1] 1 # # # [[2]] # [[2]][[1]] # [1] "a"


Solución rápida a la solución de Josh O''Brien. Hay un poco de un problema con las listas de funciones

is.NullOb <- function(x) if(!(is.function(x))) is.null(x) | all(sapply(x, is.null)) else FALSE ## Recursively step down into list, removing all such objects rmNullObs <- function(x) { if(!(is.function(x))) { x = x[!(sapply(x, is.NullOb))] lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x) } }


Usando purrr

purrr::map(lll, ~ purrr::compact(.)) %>% purrr::keep(~length(.) != 0) [[1]] [[1]][[1]] [1] 1 [[1]][[2]] [1] 2 [[1]][[3]] [1] 3 [[2]] [[2]][[1]] [1] "a" [[2]][[2]] [1] "b" [[2]][[3]] [1] "c"