14

I am wanting to return multiple values from the apply() function and place them in separate columns in R but I keep getting errors. What I am trying to do is this:

experiments$result1, experiments$result2, experiments$result3 <- apply(experiments, 1, 
function(row)
  #Some analysis here
  #return x, y, and z for column result1, result2, and result3
  x, y, z
)

Maybe this is the wrong approach to the problem. Experiments is a data frame with several columns of data. I am wanting to append columns which are the result of the analysis for each row but I don't know how to do that without loops which is not idiomatic for R. Thanks for the help ahead of time.

So here is some more exact code.

experiments$result1, experiments$result2, experiments$result3 <- apply(experiments, 1, function(row)
  x <- row["startingTemp"]*2
  y <- row["startingTemp"]*3
  z <- row["startingTemp"]*4
  return (list(x, y, z))
)

the "startingTemp" field is one of the columns in my "experiments" data frame. I'm getting errors that the type 'closure' is not subsettable and object 'z' not found.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Matthew Crews
  • 4,105
  • 7
  • 33
  • 57

2 Answers2

13

If the three values you want to return can be put in a vector (i.e. they are not of some complicated type like the results of a statistical test or a fitted model), just return the vector and apply will bind it to an 3xN matrix.

experiments$result <- apply(experiments, 1, function(row){
  x <- row["startingTemp"]*2
  y <- row["startingTemp"]*3
  z <- row["startingTemp"]*4
  c(x, y, z)
})
experiments$result1 <- experiments$result[1,]
experiments$result2 <- experiments$result[2,]
experiments$result3 <- experiments$result[3,]

If your three return values are of a complicated type (or not scalars) return them as a list (like Alan suggested) and extract them with lapply/sapply.

experiment$result1 <- lapply(experiment$result, "[[", 1)
Backlin
  • 14,612
  • 2
  • 49
  • 81
3

Try return(list(x=x,y=y,z=z)) . For each experiments you return a list of 3 value.

EDIT

The function return ONE list for each experiment.

results <- apply(exp,1,function(x) return(list(x=x,y=x*2,z=x*3))) #results is a list of lists`
experiment$res1 <- unlist(results)[attr(unlist(results),"names")=="x"]
experiment$res2 <- unlist(results)[attr(unlist(results),"names")=="y"]
experiment$res3 <- unlist(results)[attr(unlist(results),"names")=="z"]
Alan
  • 3,153
  • 2
  • 15
  • 11