仍在尝试进入 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

---编辑回答Shane的问题---

我真的不需要为结果值部分命名。我将一个聚合函数应用于第一个组件,将另一个聚合函数应用于第二个组件(minmax. 。如果两个组件的功能相同,我就不需要拆分它们)。

有帮助吗?

解决方案

(1) 列表[...]<- 我十多年前就在 r-帮助. 。从那时起它就被添加到 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 线程。

(2) 与 如果目的只是随后组合多个值并且返回值被命名,那么一个简单的替代方案是使用 with :

myfun <- function() list(a = 1, b = 2)

list[a, b] <- myfun()
a + b

# same
with(myfun(), a + b)

(3) 附加 另一种选择是附加:

attach(myfun())
a + b

添加: withattach

其他提示

我莫名其妙地在互联网上这个聪明的黑客跌跌撞撞......我不知道这是否是讨厌还是美丽的,但它可以让你创建一个“神奇”操作符,可以让你解开多个返回值转化为自己的变量。该:=功能这里定义,以下为包括后人:

':=' <- function(lhs, rhs) {
  frame <- parent.frame()
  lhs <- as.list(substitute(lhs))
  if (length(lhs) > 1)
    lhs <- lhs[-1]
  if (length(lhs) == 1) {
    do.call(`=`, list(lhs[[1]], rhs), envir=frame)
    return(invisible(NULL)) 
  }
  if (is.function(rhs) || is(rhs, 'formula'))
    rhs <- list(rhs)
  if (length(lhs) > length(rhs))
    rhs <- c(rhs, rep(list(NULL), length(lhs) - length(rhs)))
  for (i in 1:length(lhs))
    do.call(`=`, list(lhs[[i]], rhs[[i]]), envir=frame)
  return(invisible(NULL)) 
}

随着在手,你可以做你追求的:

functionReturningTwoValues <- function() {
  return(list(1, matrix(0, 2, 2)))
}
c(a, b) := functionReturningTwoValues()
a
#[1] 1
b
#     [,1] [,2]
# [1,]    0    0
# [2,]    0    0

我不知道我是怎么想那些。也许你会发现它在你的交互式工作很有帮助。用它来建立(重新)可用库(大众消费)可能不是最好的主意,但我想这是给你的。

...你知道他们说的责任和权力是什么?

一般我包输出到一个列表中,这是非常灵活的(可以有数字的任意组合,字符串,向量,矩阵,阵列,列表,对象的诠释,他输出)

所以像:

func2<-function(input) {
   a<-input+1
   b<-input+2
   output<-list(a,b)
   return(output)
}

output<-func2(5)

for (i in output) {
   print(i)
}

[1] 6
[1] 7
functionReturningTwoValues <- function() { 
  results <- list()
  results$first <- 1
  results$second <-2
  return(results) 
}
a <- functionReturningTwoValues()

我想这样的作品。

我放在一起的R包 zeallot 以解决这个问题。 zeallot包括多任务或拆包赋值运算符,%<-%。运营商的LHS是变量的任何号码分配,使用呼叫c()建成。操作者的RHS是矢量,列表,数据帧,日期对象,或任何自物体与实施destructure方法(参见?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, ..)

检查出包晕影详细信息和示例。

这个问题没有正确答案。我真的取决于你对数据的处理方式。在上面的简单示例中,我强烈建议:

  1. 让事情尽可能简单。
  2. 只要有可能,最佳实践就是保持函数矢量化。从长远来看,这提供了最大的灵活性和速度。

上面的值 1 和 2 有名称重要吗?换句话说,为什么在这个例子中将 1 和 2 命名为 a 和 b 而不仅仅是 r[1] 和 r[2] 很重要?在这种情况下需要理解的一件重要的事情是 a 和 b 是 两个向量的长度均为 1。因此,除了有 2 个不需要引用下标的新向量之外,您在进行该分配的过程中并没有真正更改任何内容:

> r <- c(1,2)
> a <- r[1]
> b <- r[2]
> class(r)
[1] "numeric"
> class(a)
[1] "numeric"
> a
[1] 1
> a[1]
[1] 1

如果您更愿意引用字母而不是索引,您还可以将名称分配给原始向量:

> names(r) <- c("a","b")
> names(r)
[1] "a" "b"
> r["a"]
a 
1 

[编辑] 考虑到您将分别对每个向量应用 min 和 max,我建议使用矩阵(如果 a 和 b 具有相同的长度和相同的数据类型)或数据帧(如果 a 和 b 具有相同的长度)但可以是不同的数据类型)或者使用上一个示例中的列表(如果它们可以具有不同的长度和数据类型)。

> r <- data.frame(a=1:4, b=5:8)
> r
  a b
1 1 5
2 2 6
3 3 7
4 4 8
> min(r$a)
[1] 1
> max(r$b)
[1] 8

解释用于此目的似乎完美。例如,该函数内你将有

x = desired_return_value_1 # (vector, matrix, etc)

y = desired_return_value_2 # (vector, matrix, etc)

returnlist = list(x,y...)

}  # end of function

主程序

x = returnlist[[1]]

y = returnlist[[2]]

是你的第二个和第三个问题 - 这就是你需要做的,因为你不能对一个赋值的左多个“左值”是什么

如何使用分配?

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

[A] 如果每个foo和bar的是单数,则没有什么错C(FOO,吧);你也可以命名成分:C(美孚= FOO,酒吧=栏)。所以,你可以访问结果 'RES' 的组分作为资源[1],RES [2];或者,在指定的情况下,作为水库[ “富”],RES [ “BAR”。

[B] 如果foo和bar是相同类型和长度的向量,然后再没有什么不妥返回cbind(FOO,吧)或rbind(FOO,吧);也可命名。在 'cbind' 的情况下,你将访问foo和bar为RES [1],RES [2]或作为水库[, “富”],RES [ “酒吧”]。你可能还喜欢返回一个数据帧,而不是一个矩阵:

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

和访问它们的资源$美孚,水库$酒吧。这也将很好地工作,如果foo和bar是相同长度的,但不是相同的类型(例如foo是数的向量,棒材字符串的向量)。

[C] 如果foo和酒吧有足够的不同并不如上方便结合起来,那么你肯定shuld返回一个列表。

例如,你的功能可能适合的线性模型和 还计算预测值,因此你可以有

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

然后你会return list(Foo=foo,Bar=bar)然后访问内容摘要水库$酒吧为水库$美孚,预测值

源: http://r.789695.n4.nabble.com/How-to-return-multiple-values-in-a-function-td858528.html

如果你想你的函数的输出返回给全球环境,你可以在这个例子中使用list2env,如:

myfun <- function(x) { a <- 1:x
                       b <- 5:x
                       df <- data.frame(a=a, b=b)

                       newList <- list("my_obj1" = a, "my_obj2" = b, "myDF"=df)
                       list2env(newList ,.GlobalEnv)
                       }
    myfun(3)

这个功能将在全球环境创建三个对象:

> my_obj1
  [1] 1 2 3

> my_obj2
  [1] 5 4 3

> myDF
    a b
  1 1 5
  2 2 4
  3 3 3

要由功能获取的多个输出和从函数内将它们保持在期望的格式可以将输出保存到硬盘(在工作目录),然后从函数外部加载它们:

myfun <- function(x) {
                      df1 <- ...
                      df2 <- ...
                      save(df1, file = "myfile1")
                      save(df2, file = "myfile2")
}
load("myfile1")
load("myfile2")
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top