4
votes

Desired

is having a R function

listNames = function(l) {
   # return list element names
}

that returns all list elements, but ignores the column names of data frames on first level

listNames(a)
[1] "b.df1" "b.e" "c" "df2"  

from a nested list:

a = list(b = list(df1 = data.frame(col = c(1,2)), e = NULL), c = NULL, df2 = data.frame(c12 = c(1,2),c34 = c(3,4)))

Tried so far

unlist returns also data.frame columns. I assume because data.frames are also considered lists

names(unlist(a,recursive = FALSE))
[1] "b.df1"   "b.e"     "df2.c12" "df2.c34"

and names(a) skips nested elements

names(a)
[1] "b"   "c"   "df2"
2
Are you looking for names(a)?Martin Gal
@MartinGal no, see editsequoia

2 Answers

3
votes

You can write a recursive function stopping when there is no list or a data.frame.

listNames = function(l) {
  if(!is.list(l) | is.data.frame(l)) TRUE
  else (lapply(l, listNames))
}

names(unlist(listNames(a)))
#[1] "b.df1" "b.e"   "c"     "df2"
2
votes

Using an external package, this can be done with rrapply::rrapply(), which extends base rapply to avoid recursing into individual data.frame columns.

One possible approach is to include "data.frame" in the evaluated classes and return the name of each evaluated element, which works for arbitrary levels of nesting:

library(rrapply)

rrapply(a, classes = c("ANY", "data.frame"), f = function(x, .xname) .xname, how = "unlist")

#> b.df1   b.e     c   df2 
#> "df1"   "e"   "c" "df2"