Home > Mobile >  Add one variable containing the name of each FINAL list (in a list of lists) in R
Add one variable containing the name of each FINAL list (in a list of lists) in R

Time:12-04

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?

CodePudding user response:

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).

CodePudding user response:

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
  • Related