1

I have a list of lists like ll:

ll <- list(a = list(data.frame(c = 1, d = 2), data.frame(h = 3, j = 4)), b = list(data.frame(c = 5, d = 6), data.frame(h = 7, j = 9)))

I want to add one variable grp to each final list. This variable (grp) has to contain the name/value of each list. Therefore the new list of lists may look like ls:

ls <- list(a = list(data.frame(c = 1, d = 2, grp = 1), data.frame(h = 3, j = 4, grp = 2)), b = list(data.frame(c = 5, d = 6, grp = 1), data.frame(h = 7, j = 9, grp = 2)))

NOTE: The grp may not follow a sequence from 1:n. The approach I look for may be similar to the following one bind_rows(df, .id = 'grp'). The only point is that in this case, I don´t want to row bind (at least not in this way but in this other Unlist LAST level of a list in R)

Any clue?

vog
  • 770
  • 5
  • 11

2 Answers2

2

You can simply cycle through the levels with lapply

setNames( lapply( 1:length(ll), function(x) lapply( 1:length(ll[[x]]), 
  function(y) cbind(ll[[x]][[y]],grp=y ) ) ), names(ll) )
$a
$a[[1]]
  c d grp
1 1 2   1

$a[[2]]
  h j grp
1 3 4   2


$b
$b[[1]]
  c d grp
1 5 6   1

$b[[2]]
  h j grp
1 7 9   2
Andre Wildberg
  • 12,344
  • 3
  • 12
  • 29
  • It may not follow a sequence from 1:n. The approach I look for may be similar to the following one ```bind_rows(df, .id = 'grp')```. The only point is that in this case, I don´t want to row bind (at least not in this way but in this other https://stackoverflow.com/questions/70205748/unlist-last-level-of-a-list-in-r) – vog Dec 03 '21 at 15:26
  • @vog You may put that in the question. That's critical information for any potential answer. – Andre Wildberg Dec 03 '21 at 15:31
  • 1
    Sure! Question edited. Thank you – vog Dec 03 '21 at 15:44
1

From the post it seems the groups are defined iteratively for each nested list. We can use a seq_along to create the groups, and apply this on each element of the list ll.
base R

lapply(ll, \(.){
  Map(function(i, n) {n$grp = i ; n}, seq_along(.), .)
})
$a
$a[[1]]
  c d grp
1 1 2   1
$a[[2]]
  h j grp
1 3 4   2
$b
$b[[1]]
  c d grp
1 5 6   1
$b[[2]]
  h j grp
1 7 9   2

purrr

map(ll, ~imap(.x, ~{.x$grp <- .y ; .x}))

For similar approaches using purely lapply, mapply or purrr::map, see this SO post. In this approach the only difference with the expected result is the class of the vector, an integer instead of a numeric, see waldo::compare(ls, ll).

Donald Seinen
  • 4,179
  • 5
  • 15
  • 40
  • It may not follow a sequence from 1:n. The approach I look for may be similar to the following one ```bind_rows(df, .id = 'grp')```. The only point is that in this case, I don´t want to row bind (at least not in this way but in this other https://stackoverflow.com/questions/70205748/unlist-last-level-of-a-list-in-r) – vog Dec 03 '21 at 15:26
  • @vog please update your expected output in the original post to reflect your requirements (with edge cases illustrating the problem) - it is unclear to me what the criteria for the `grp` variable are. Can't offer concrete solutions or approaches to *may*. `bind_rows` ... binds rows, which is not shown in the expected output `ls` in the original post. – Donald Seinen Dec 03 '21 at 15:46
  • 1
    The question is edited now. Thank you! – vog Dec 03 '21 at 18:05