Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reduce a nested list with varying length

Tags:

list

r

reduce

Say i have a list:

  mylist=list(list(data.frame(a=3,b=2,c=4),data.frame(d=5,e=6,h=8),data.frame(k=2,e=3,b=5,m=5)),
              list(data.frame(a=32,b=22,c=42),data.frame(d=5,e=63,h=82),data.frame(k=2,e=33,b=5,m=5)),
              list(data.frame(a=33,b=21,k=41,c=41),data.frame(d=5,e=61,h=80),data.frame(k=22,e=3,b=5,m=5)))

Then I try to get a new list by cbind each element of the list, for example cbind mylist[[1]][[1]]withmylist[[2]][[1]]andmylist[[3]][[1]]

The function:

newlist=lapply(seq_along(mylist[[1]]), function(x){    
    newlist=Reduce("cbind",c(mylist[[1]][x],mylist[[-1]][x]))
    return(newlist)

})

I get:
Error in mylist[[-1]] : attempt to select more than one element  

But the lapply works if the list is only:

mylistshort=mylist[-3]

The desired result is:

[[1]]
  a b c  a  b  c a  b  k  c
1 3 2 4 32 22 42 33 21 41 41

[[2]]
  d e h d e  h  d e  h
1 5 6 8 5 63 82 5 61 80

[[3]]
  k e b m k e  b m k  e m
1 2 3 5 5 2 33 5 5 22 3 5

So how do I reduce a list with length bigger then 2? Best Regards

like image 933
user1665355 Avatar asked Dec 14 '22 16:12

user1665355


1 Answers

Another idea:

.mapply(cbind, mylist, NULL)
#[[1]]
#  a b c  a  b  c  a  b  k  c
#1 3 2 4 32 22 42 33 21 41 41
#
#[[2]]
#  d e h d  e  h d  e  h
#1 5 6 8 5 63 82 5 61 80
#
#[[3]]
#  k e b m k  e b m  k e b m
#1 2 3 5 5 2 33 5 5 22 3 5 5

EDIT: some comments

You 're, basically, looking for a "vectorised" cbind. You can use a for loop for this, but R has a built-in "vectorisation" tool: mapply (not neccessarily faster, but cleaner). You could use mapply, for a specific number of arguments, like this:

mapply(function(x, y, z) cbind(x, y, z), mylist[[1]], mylist[[2]], mylist[[3]])

But, you could, also, pass a "variable-length arguments" (...) to make it more practical:

mapply(function(...) cbind(...), mylist[[1]], mylist[[2]], mylist[[3]])

cbind is built to know how to handle ... arguments:

mapply(cbind, mylist[[1]], mylist[[2]], mylist[[3]])

This, still, is not flexible because you'll have to specify each argument since mapply accepts only .... do.call is handy for cases where you have a function's arguments in a "list":

do.call(mapply, c(cbind, mylist))

R, has a dotted mapply that accepts its ... arguments as a list, looks cooler, and can replace do.call:

.mapply(FUN = cbind, dots = mylist, MoreArgs = NULL)
like image 68
alexis_laz Avatar answered Jan 03 '23 05:01

alexis_laz