Home > Blockchain >  Find which elements of a nested list are dataframes
Find which elements of a nested list are dataframes

Time:11-02

Suppose that I have a nested list like the following

test <- list(
  a = data.frame(x = 1),
  b = "foo",
  c = list(
    d = 1:5,
    e = data.frame(y = 1),
    f = "a",
    list(g = "hello")
  )
)
test
#> $a
#>   x
#> 1 1
#> 
#> $b
#> [1] "foo"
#> 
#> $c
#> $c$d
#> [1] 1 2 3 4 5
#> 
#> $c$e
#>   y
#> 1 1
#> 
#> $c$f
#> [1] "a"
#> 
#> $c[[4]]
#> $c[[4]]$g
#> [1] "hello"

I want to know the location of character elements in this nested list. In this case, I want to return a named vector or a named list with TRUE if the element is a character and FALSE otherwise.

I can do that with rapply, that unlists everything:

rapply(test, is.character)
#>   a.x     b   c.d c.e.y   c.f   c.g 
#> FALSE  TRUE FALSE FALSE  TRUE  TRUE

However, I can’t do that to find all dataframes because rapply() also unlists dataframes (note that the first element is a.x and not only a).

rapply(test, is.data.frame)
#>   a.x     b   c.d c.e.y   c.f   c.g 
#> FALSE FALSE FALSE FALSE FALSE FALSE

Therefore, is there a way to find which elements of a nested list are dataframes? Note that the solution should work with any number of levels in the nested list.

I’m looking for a solution in base R only.

CodePudding user response:

1) rrapply

library(rrapply)

cls <- c("data.frame", "ANY")
rrapply(test, f = is.data.frame, classes = cls, how = "unlist")
##     a     b   c.d   c.e   c.f   c.g 
##  TRUE FALSE FALSE  TRUE FALSE FALSE 

2) recursion

findDF <- function(x) {
  if (is.data.frame(x)) TRUE
  else if (is.list(x)) lapply(x, findDF)
  else FALSE
}

unlist(findDF(test))
##     a     b   c.d   c.e   c.f   c.g 
##  TRUE FALSE FALSE  TRUE FALSE FALSE 
  • Related