Display names of column of recursive list as tree

Here is a recursive solution:

nametree <- function(X, prefix = "")
  if( is.list(X) )
    for( i in seq_along(X) ) { 
      cat( prefix, names(X)[i], "\n", sep="" )
      nametree(X[[i]], paste0(prefix, "  "))
    }
X <- list(X = list( A = list( a1=1:10, a2=1:10 ), B = 1:10 ))
nametree(X)
# X
#   A
#     a1
#     a2
#   B

Displaying the tree structure with branches rather than spaces is slightly trickier:

nametree <- function(X, prefix1 = "", prefix2 = "", prefix3 = "", prefix4 = "")
  if( is.list(X) )
    for( i in seq_along(X) ) { 
      cat( if(i<length(X)) prefix1 else prefix3, names(X)[i], "\n", sep="" )
      prefix <- if( i<length(X) ) prefix2 else prefix4
      nametree(
        X[[i]], 
        paste0(prefix, "├──"),
        paste0(prefix, "│  "),
        paste0(prefix, "└──"),
        paste0(prefix, "   ")
      )
    }
nametree(X)
# X
# +--A
# ¦  +--a1
# ¦  +--a2
# +--B
# +--C
#    +--a
#    +--b

A simple example:

> mylist <- list(A=data.frame(A1=1:3,A2=4:6),B=7:9)
> out <- lapply(mylist,names)
$A
[1] "A1" "A2"

$B
NULL

This assumes you only have dataframes one level below the list...so it's not recursive per se, but it sounds like this is similar to your data structure.

DrMike and Henrik's suggestion to use str(mylist) will be recursive and is, in fact, able to control both how deep into the structure and the display of the output.

SimonO101's example of recursion:

> df <- data.frame( A = runif(3) , B = runif(3) )
> ll <- list( A = df , B = list( C = df , D = df ) , E = 1 )
> str(ll)
List of 3
 $ A:'data.frame':      3 obs. of  2 variables:
  ..$ A: num [1:3] 0.948 0.356 0.467
  ..$ B: num [1:3] 0.2319 0.7574 0.0312
 $ B:List of 2
  ..$ C:'data.frame':   3 obs. of  2 variables:
  .. ..$ A: num [1:3] 0.948 0.356 0.467
  .. ..$ B: num [1:3] 0.2319 0.7574 0.0312
  ..$ D:'data.frame':   3 obs. of  2 variables:
  .. ..$ A: num [1:3] 0.948 0.356 0.467
  .. ..$ B: num [1:3] 0.2319 0.7574 0.0312
 $ E: num 1

Some examples of output:

> str(mylist)
List of 2
 $ A:'data.frame':      3 obs. of  2 variables:
  ..$ A1: int [1:3] 1 2 3
  ..$ A2: int [1:3] 4 5 6
 $ B: int [1:3] 7 8 9

> str(mylist, give.attr=FALSE, give.length=FALSE, give.head=FALSE, vec.len=0, 
indent.str="|", comp.str="----")
List of 2
|----A:'data.frame':    3 obs. of  2 variables:
| ..$ A1:NULL ...
| ..$ A2:NULL ...
|----B:NULL ...

You can use the data.tree package. For example:

x <- list( A = list( a1 = list(data = 1:10), b1 = list(data = 1:100 )), B = list(data = c(1, 3, 5) ))
library(data.tree)
xtree <- FromListSimple(x, nodeName = "X")
xtree

This prints out:

   levelName
1 X         
2  ¦--A     
3  ¦   ¦--a1
4  ¦   °--b1
5  °--B  

Or you can convert the data into a printable format:

print(xtree, maxData = function(node) if (is.null(node$data)) 0 else max(node$data))

Which shows:

   levelName maxData
1 X                0
2  ¦--A            0
3  ¦   ¦--a1      10
4  ¦   °--b1     100
5  °--B            5

Finally, to show the names of a node:

names(xtree$children)

This prints:

[1] "A" "B"

Tags:

R