Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extract colnames from a nested list of data.frames

I have a nested list of data.frames, what is the easiest way to get the column names of all data.frames?

Example:

d = data.frame(a = 1:3, b = 1:3, c = 1:3)

l = list(a = d, list(b = d, c = d))

Result:

$a
[1] "a" "b" "c"

$b
[1] "a" "b" "c"

$c
[1] "a" "b" "c"
like image 573
user680111 Avatar asked Jan 20 '20 09:01

user680111


2 Answers

Using an external package, this is also straightforward with rrapply() in the rrapply-package (and works for arbitrary levels of nesting):

library(rrapply)

rrapply(l, classes = "data.frame", f = colnames, how = "flatten")
#> $a
#> [1] "a" "b" "c"
#> 
#> $b
#> [1] "a" "b" "c"
#> 
#> $c
#> [1] "a" "b" "c"

## deeply nested list
l2 <- list(a = d, list(b = d, list(c = list(e = list(f = list(g = d))))))

rrapply(l2, classes = "data.frame", f = colnames, how = "flatten")
#> $a
#> [1] "a" "b" "c"
#> 
#> $b
#> [1] "a" "b" "c"
#> 
#> $g
#> [1] "a" "b" "c"
like image 67
Joris C. Avatar answered Sep 21 '22 07:09

Joris C.


Here is a base R solution.

You can define a customized function to flatten your nested list (which can deal nested list of any depths, e.g., more than 2 levels), i.e.,

flatten <- function(x){  
  islist <- sapply(x, class) %in% "list"
  r <- c(x[!islist], unlist(x[islist],recursive = F))
  if(!sum(islist))return(r)
  flatten(r)
}

and then use the following code to achieve the colnames

out <- Map(colnames,flatten(l))

such that

> out
$a
[1] "a" "b" "c"

$b
[1] "a" "b" "c"

$c
[1] "a" "b" "c"

Example with a deeper nested list

l <- list(a = d, list(b = d, list(c = list(e = list(f= list(g = d))))))
> l
$a
  a b c
1 1 1 1
2 2 2 2
3 3 3 3

[[2]]
[[2]]$b
  a b c
1 1 1 1
2 2 2 2
3 3 3 3

[[2]][[2]]
[[2]][[2]]$c
[[2]][[2]]$c$e
[[2]][[2]]$c$e$f
[[2]][[2]]$c$e$f$g
  a b c
1 1 1 1
2 2 2 2
3 3 3 3

and you will get

> out
$a
[1] "a" "b" "c"

$b
[1] "a" "b" "c"

$c.e.f.g
[1] "a" "b" "c"
like image 21
ThomasIsCoding Avatar answered Sep 22 '22 07:09

ThomasIsCoding