还在试着进入R逻辑…什么是解包(在LHS上)一个函数返回多个值的结果的“最佳”方法?
显然我不能这么做:
R> functionReturningTwoValues <- function() { return(c(1, 2)) }
R> functionReturningTwoValues()
[1] 1 2
R> a, b <- functionReturningTwoValues()
Error: unexpected ',' in "a,"
R> c(a, b) <- functionReturningTwoValues()
Error in c(a, b) <- functionReturningTwoValues() : object 'a' not found
我真的必须做以下事情吗?
R> r <- functionReturningTwoValues()
R> a <- r[1]; b <- r[2]
或者R程序员会这样写:
R> functionReturningTwoValues <- function() {return(list(first=1, second=2))}
R> r <- functionReturningTwoValues()
R> r$first
[1] 1
R> r$second
[1] 2
——被编辑来回答谢恩的问题——
我真的不需要给结果值部分命名。我将一个聚合函数应用于第一个组件,另一个应用于第二个组件(最小值和最大值)。如果这两个组件是相同的函数,我就不需要拆分它们了)。
(一)
如果foo和bar都是一个数字,那么c(foo,bar)没有问题;你也可以命名这些组件:c(Foo= Foo,Bar= Bar)。所以你可以访问结果res的组件res[1] res[2];或在命名的情况下,如res["Foo"], res["BAR"]。
[B]
如果foo和bar是相同类型和长度的向量,那么返回cbind(foo,bar)或rbind(foo,bar)也没有问题;同样值得注意的。在'cbind'情况下,您将访问foo和bar为res[,1], res[,2]或res[," foo "], res[," bar "]。你可能更喜欢返回一个数据框架而不是一个矩阵:
data.frame(Foo=foo,Bar=bar)
并访问它们为res$Foo res$Bar如果foo和bar的长度相同但类型不同(例如,foo是一个数字向量,bar是一个字符串向量),这也可以很好地工作。
[C]
如果foo和bar完全不同,不能像上面那样方便地组合,那么你肯定应该返回一个列表。
例如,你的函数可能适合线性模型
还要计算预测值,这样你就可以
LM<-lm(....) ; foo<-summary(LM); bar<-LM$fit
然后你会返回list(Foo= Foo, Bar= Bar),然后访问摘要res$Foo,预测值res$Bar
来源:http://r.789695.n4.nabble.com/How-to-return-multiple-values-in-a-function-td858528.html
那么使用assign呢?
functionReturningTwoValues <- function(a, b) {
assign(a, 1, pos=1)
assign(b, 2, pos=1)
}
您可以通过引用传递想要传递的变量的名称。
> functionReturningTwoValues('a', 'b')
> a
[1] 1
> b
[1] 2
如果需要访问现有值,则与assign相反的是get。
(1)列表[…我十多年前就在r-help上发过这篇文章。从那时起,它被添加到gsubfn包中。它不需要一个特殊的操作符,但要求左边使用list[…]像这样:
library(gsubfn) # need 0.7-0 or later
list[a, b] <- functionReturningTwoValues()
如果你只需要第一个或第二个组件,这些也可以工作:
list[a] <- functionReturningTwoValues()
list[a, ] <- functionReturningTwoValues()
list[, b] <- functionReturningTwoValues()
(当然,如果你只需要一个值,那么functionReturningTwoValues()[[1]]或functionReturningTwoValues()[[2]]就足够了。)
有关更多示例,请参阅引用的r-help线程。
如果意图仅仅是随后组合多个值,并且返回值被命名,那么一个简单的替代方法是使用with:
myfun <- function() list(a = 1, b = 2)
list[a, b] <- myfun()
a + b
# same
with(myfun(), a + b)
另一种替代方法是attach:
attach(myfun())
a + b
附加:与和附加
我组装了一个R包热机来解决这个问题。Zeallot包含一个多重赋值或解包赋值操作符%<-%。运算符的LHS是要赋值的任意数量的变量,通过调用c()构建。操作符的RHS是一个向量、列表、数据帧、日期对象或任何具有已实现的解构方法的自定义对象(参见?zeallot::destructure)。
以下是一些基于原始帖子的例子,
library(zeallot)
functionReturningTwoValues <- function() {
return(c(1, 2))
}
c(a, b) %<-% functionReturningTwoValues()
a # 1
b # 2
functionReturningListOfValues <- function() {
return(list(1, 2, 3))
}
c(d, e, f) %<-% functionReturningListOfValues()
d # 1
e # 2
f # 3
functionReturningNestedList <- function() {
return(list(1, list(2, 3)))
}
c(f, c(g, h)) %<-% functionReturningNestedList()
f # 1
g # 2
h # 3
functionReturningTooManyValues <- function() {
return(as.list(1:20))
}
c(i, j, ...rest) %<-% functionReturningTooManyValues()
i # 1
j # 2
rest # list(3, 4, 5, ..)
有关更多信息和示例,请查看软件包插图。