Re: [R] How to return multiple values in a function

From: Ted Harding <Ted.Harding_at_manchester.ac.uk>
Date: Mon, 23 Jun 2008 10:37:36 +0100 (BST)


On 23-Jun-08 09:04:42, Wacek Kusnierczyk wrote:
> Hans-Joerg Bibiko wrote:

>> On 23 Jun 2008, at 10:23, Gundala Viswanath wrote:
>>> I apologize for this newbie question. But I can't seem
>>> to find in R online manual.
>>>
>>> 1. How can I return two values in a function?
>>> 2. How can I capture the values again of this function?
>>>
>>> myfunc <- function (array) {
>>>   # do something with array
>>>   # get something assign to "foo" and "bar"
>>>   print(foo)
>>>   print(bar)
>>>
>>>  # how can I return "foo" and "bar" ?
>>> }
>>>
>>> # Is this the way to capture it?
>>> (nfoo,nbar) <- myfunc(some_array)
>>>
>>
>> One way would be :
>>
>> myfunc <- function (array) {
>>
>>   # do something with array
>>   # get something assign to "foo" and "bar"
>>   result <- c(foo, bar)
>>   return(result)
>>  # how can I return "foo" and "bar" ?
>> }
>>
>> res <- myfunc(some_array)
>> res[1]
>> [1] "foo.stuff"
>> res[2]
>> [1] "bar.stuff"
>>

>
> safer to wrap the results into a list; if both foo and bar
> are vectors, the returned result would be *one* vector rather
> than a collection of two vectors. so the generic pattern would be:
>
> <function> = function(<args>) {
> <body>
> list(<values>)
> }
>
> ?return
>
> vQ

Gundala Viswanath original request about getting the result in the form

  (nfoo,nbar) <- myfunc(some_array)

suggests inspiration from MatLab/octave. That's not how R syntax handles it!

Wacek Kusnierczyk's suggestion of returning a list is certainly safe and general. However, in particular cases it may well be more convenient and manageable to use more specific structures.

[A]
If each of foo and bar is a single number, then there's nothing wrong with c(foo,bar); and you can also name the components: c(Foo=foo,Bar=bar). So you could access the components of the result 'res' as res[1], res[2]; or, in the named case, as res["Foo"], res["BAR"].

[B]
If foo and bar are vectors of the same type and length, then again there's nothing wrong with returning cbind(foo,bar) or rbind(foo,bar); likewise nameable. In the 'cbind' case, you would access foo and bar as res[,1], res[,2] or as res[,"Foo"], res[,"Bar"]. You might also prefer to return a dataframe rather than a matrix:

  data.frame(Foo=foo,Bar=bar)

and access them as res$Foo, res$Bar. This would also work well if foo and bar were of the same length but not of the same type (e.g. foo is a vector of numbers, bar a vector of character strings).

[C]
If foo and bar are sufficiently different not to combine conveniently as above, then you shuld definitely return a list.

For example, your function might fit a linear model and also calculate predicted values, so you could have

  LM<-lm(....) ; foo<-summary(LM); bar<-LM$fit

and then you would return list(Foo=foo,Bar=bar) and then access the summary as res$Foo, the predicted values as res$Bar.

Hoping this helps,
Ted.



E-Mail: (Ted Harding) <Ted.Harding_at_manchester.ac.uk> Fax-to-email: +44 (0)870 094 0861
Date: 23-Jun-08                                       Time: 10:37:34
------------------------------ XFMail ------------------------------

______________________________________________
R-help_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code. Received on Mon 23 Jun 2008 - 09:40:03 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Mon 23 Jun 2008 - 10:30:46 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-help. Please read the posting guide before posting to the list.

list of date sections of archive