Returning multiple objects in an R function
RFunctionR Problem Overview
How can I return multiple objects in an R function? In Java, I would make a Class, maybe Person
which has some private variables and encapsulates, maybe, height
, age
, etc.
But in R, I need to pass around groups of data. For example, how can I make an R function return both an list of characters and an integer?
R Solutions
Solution 1 - R
Unlike many other languages, R functions don't return multiple objects in the strict sense. The most general way to handle this is to return a list
object. So if you have an integer foo
and a vector of strings bar
in your function, you could create a list that combines these items:
foo <- 12
bar <- c("a", "b", "e")
newList <- list("integer" = foo, "names" = bar)
Then return
this list.
After calling your function, you can then access each of these with newList$integer
or newList$names
.
Other object types might work better for various purposes, but the list
object is a good way to get started.
Solution 2 - R
Similarly in Java, you can create a S4 class in R that encapsulates your information:
setClass(Class="Person",
representation(
height="numeric",
age="numeric"
)
)
Then your function can return an instance of this class:
myFunction = function(age=28, height=176){
return(new("Person",
age=age,
height=height))
}
and you can access your information:
aPerson = myFunction()
aPerson@age
aPerson@height
Solution 3 - R
Is something along these lines what you are looking for?
x1 = function(x){
mu = mean(x)
l1 = list(s1=table(x),std=sd(x))
return(list(l1,mu))
}
library(Ecdat)
data(Fair)
x1(Fair$age)
Solution 4 - R
You can also use super-assignment.
Rather than "<-" type "<<-". The function will recursively and repeatedly search one functional level higher for an object of that name. If it can't find one, it will create one on the global level.
Solution 5 - R
You could use for()
with assign()
to create many objects.
See the example from assign()
:
for(i in 1:6) { #-- Create objects 'r.1', 'r.2', ... 'r.6' --
nam <- paste("r", i, sep = ".")
assign(nam, 1:i)
Looking the new objects
ls(pattern = "^r..$")
Solution 6 - R
One way to handle this is to put the information as an attribute on the primary one. I must stress, I really think this is the appropriate thing to do only when the two pieces of information are related such that one has information about the other.
For example, I sometimes stash the name of "crucial variables" or variables that have been significantly modified by storing a list of variable names as an attribute on the data frame:
attr(my.DF, 'Modified.Variables') <- DVs.For.Analysis$Names.of.Modified.Vars
return(my.DF)
This allows me to store a list of variable names with the data frame itself.