Home > Enterprise >  flatten a list of lists without recursive=FALSE
flatten a list of lists without recursive=FALSE

Time:04-30

I have a list that contains some other lists, but also contains additional objects that aren't lists such as data frames. I want to flatten this to a single list, but the usual advice (see How to flatten a list of lists? or converting a list of lists in a single list) of unlist(..., recursive = FALSE) won't work because it operates on the data.frame as well.

> d <- list(list(a = 1, b = 2), c = data.frame(1:4))
> d
[[1]]
[[1]]$a
[1] 1

[[1]]$b
[1] 2


$c
  X1.4
1    1
2    2
3    3
4    4
> unlist(d, recursive = FALSE)
$a
[1] 1

$b
[1] 2

$c.X1.4
[1] 1 2 3 4

The expected result is that $c will retain the same data.frame structure.

The only solution I have so far is to add an additional layer of lists to all non-lists object before unlisting but its a very unelegant solution.

> unlist(lapply(d, function(x) if(!inherits(x, "list")) list(x) else x), recursive = FALSE)
$a
[1] 1

$b
[1] 2

$c
  X1.4
1    1
2    2
3    3
4    4

This works, but does anyone have a more direct idea? (I'd greatly prefer a base R solution, not tidyverse.)

CodePudding user response:

Admittedly, not necessarily "elegant", but still:

library(rrapply)

c(rrapply(rrapply(d, classes = "list", how = "flatten"), how = "flatten"),
  rrapply(d, f = as.data.frame, classes = "data.frame", how = "flatten"))

$a
[1] 1

$b
[1] 2

$c
  X1.4
1    1
2    2
3    3
4    4

As @tmfmnk mentioned in the comments, in your particular case, even this would work:

rrapply(d, classes = c("numeric", "data.frame"), how = "flatten")

So you basically define what classes should not be flattened further. This particular solution I'd then indeed call "elegant".

CodePudding user response:

You can use a recursive function (inspired by this answer).

flattenMixed <- function(x) {
  if (is.data.frame(x)) return(list(x))
  if (!is.list(x)) return(x)
  unlist(lapply(x, flattenMixed), FALSE)
}

flattenMixed(d)

$a
[1] 1

$b
[1] 2

$c
  X1.4
1    1
2    2
3    3
4    4
  •  Tags:  
  • r
  • Related