Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return multiple lists in mapply [duplicate]

Tags:

r

mapply

I have a function which I am applying across a list of data frames or matrices (df) using mapply. The function outputs four different types of data frames (ex. a:d) based on some criteria of transformation of the original data frame, but I am having issues as function will only let me output one. I have tried to collate them into a list, but when I run a simplified function, I get this.

df1<-matrix(rnorm(10), nrow=10, ncol=10)
df2<-df1
df<-list(df1, df2)

func<-function (x) {
  a<-x*1
  b<-x*2
  c<-x*3
  d<-x*4
  return(list(a,b,c,d))
}

finalresult<-mapply(func, x=df)

str(finalresult)

List of 8
 $ : num [1:10, 1:10] -3.211 -0.121 -0.2 0.491 1.118 ...
 $ : num [1:10, 1:10] -6.422 -0.242 -0.4 0.982 2.235 ...
 $ : num [1:10, 1:10] -9.633 -0.362 -0.6 1.473 3.353 ...
 $ : num [1:10, 1:10] -12.844 -0.483 -0.8 1.964 4.471 ...
 $ : num [1:10, 1:10] -3.211 -0.121 -0.2 0.491 1.118 ...
 $ : num [1:10, 1:10] -6.422 -0.242 -0.4 0.982 2.235 ...
 $ : num [1:10, 1:10] -9.633 -0.362 -0.6 1.473 3.353 ...
 $ : num [1:10, 1:10] -12.844 -0.483 -0.8 1.964 4.471 ...
 - attr(*, "dim")= int [1:2] 4 2

In this case you can see it is just giving me the list of the four output data frames (a:d) from df1 and then appends the next set of outputs from df2 right after. I want to have an output where each data frame transformation is put in a list where I can access it by category (ex. finalresults$a). Any help would be very much appreciated!

Thanks, -Chelsea

like image 919
Chelsea Avatar asked Jan 12 '14 04:01

Chelsea


2 Answers

How about:

Use mapply but don't simplify.

result1 <- mapply(func, x=df, SIMPLIFY=FALSE)

Iterate over the indices (this assumes both lists in the result are the same length); for each index i, use lapply to pull out the ith element of each list in result1.

 result2 <- lapply(seq_along(result1[[1]]),
              function(i) lapply(result1,"[[",i))

I tried a little bit to shorten/obfuscate this still further (i.e. remove the need to define an anonymous function), but with nested lapplys I can't quite figure out how to make it work.

like image 124
Ben Bolker Avatar answered Oct 07 '22 00:10

Ben Bolker


Here is a solution that gives what you want. It basically names your list returns and then aggregates by the name.

df1<-matrix(rnorm(10), nrow=10, ncol=10)
df2<-df1
df<-list(df1, df2)
namesToReferTo = letters[1:4]
func<-function (x) {
  a<-x*1; b<-x*2; c<-x*3; d<-x*4
  retList = list(a,b,c,d)
  names(retList)=namesToReferTo
  return(retList)
}
finalresult = lapply(namesToReferTo, function(y) { lapply(lapply(df,func), function(x) { x[[y]] }) } )
# alternatively: finalresult = lapply(namesToReferTo, function(y) { Map(function(x) { return(x[[y]])} , lapply(df,func)) } )
names(finalresult) = namesToReferTo
str(finalresult)
finalresult$b
like image 23
Hans Roggeman Avatar answered Oct 06 '22 23:10

Hans Roggeman