还在试着进入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

——被编辑来回答谢恩的问题——

我真的不需要给结果值部分命名。我将一个聚合函数应用于第一个组件,另一个应用于第二个组件(最小值和最大值)。如果这两个组件是相同的函数,我就不需要拆分它们了)。


当前回答

那么使用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

附加:与和附加

这只是为了完整,而不是因为我个人喜欢它。你可以用管道%>%输出结果,用花括号{}求值,用双箭头<<-将变量写入父环境。

library(tidyverse)
functionReturningTwoValues() %>% {a <<- .[1]; b <<- .[2]}

更新: 您还可以使用zeallot包中的多重赋值操作符::%<-%

c(a, b) %<-% list(0, 1)

那么使用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。

我将发布一个函数,以向量的方式返回多个对象:

Median <- function(X){
  X_Sort <- sort(X)
  if (length(X)%%2==0){
    Median <- (X_Sort[(length(X)/2)]+X_Sort[(length(X)/2)+1])/2
  } else{
    Median <- X_Sort[(length(X)+1)/2]
  }
  return(Median)
}

这是我用来计算中位数的函数。我知道R中有一个内置函数叫做median(),但尽管如此,我还是编写了它来构建其他函数,通过使用我刚刚编写的median()函数来计算数值数据集的四分位数。Median()函数是这样工作的:

如果数值向量X有偶数个元素(即length(X)%%2==0),则通过将元素sort(X)[length(X)/2]和sort(X)[(length(X)/2+1)]求平均值来计算中位数。 如果X没有偶数个元素,则中位数为sort(X)[(length(X)+1)/2]。

关于QuartilesFunction():

QuartilesFunction <- function(X){
X_Sort <- sort(X) # Data is sorted in ascending order

if (length(X)%%2==0){
  
  # Data number is even
  
  HalfDN <- X_Sort[1:(length(X)/2)] 
  HalfUP <- X_Sort[((length(X)/2)+1):length(X)]
  
  QL <- Median(HalfDN)
  QU <- Median(HalfUP)
  
  QL1 <- QL
  QL2 <- QL
  QU1 <- QU
  QU2 <- QU
  QL3 <- QL
  QU3 <- QU
  
  Quartiles <- c(QL1,QU1,QL2,QU2,QL3,QU3)
  names(Quartiles) = c("QL (1)", "QU (1)", "QL (2)", "QU (2)","QL (3)", "QU (3)")
  
} else{ # Data number is odd
  
  # Including the median
  
  Half1DN <- X_Sort[1:((length(X)+1)/2)] 
  Half1UP <- X_Sort[(((length(X)+1)/2)):length(X)]
  
  QL1 <- Median(Half1DN)
  QU1 <- Median(Half1UP)
  
  # Not including the median
  
  Half2DN <- X_Sort[1:(((length(X)+1)/2)-1)] 
  Half2UP <- X_Sort[(((length(X)+1)/2)+1):length(X)]
  
  QL2 <- Median(Half2DN)
  QU2 <- Median(Half2UP)
  
  # Methods (1) and (2) averaged
  
  QL3 <- (QL1+QL2)/2
  QU3 <- (QU1+QU2)/2
  
  Quartiles <- c(QL1,QU1,QL2,QU2,QL3,QU3)
  names(Quartiles) = c("QL (1)", "QU (1)", "QL (2)", "QU (2)","QL (3)", "QU (3)") 
}
return(Quartiles)
}

该函数通过以下三种方法返回数值向量的四分位数:

当数值向量x的元素数为奇数时,丢弃计算四分位数的中位数。 当数值向量x的元素个数为奇数时,保持四分位数计算的中位数。 对方法1和方法2得到的结果求平均值。

当数字向量X的元素个数为偶数时,三种方法重合。

QuartilesFunction()的结果是一个向量,它描述了使用上述三种方法计算出的第一和第三个四分位数。

2021年,我经常用这个词。

Tidyverse包有一个名为LST的函数,它在创建列表时为列表元素分配名称。 Post,我使用list2env()来分配变量或直接使用列表

library(tidyverse)
fun <- function(){
  a<-1
  b<-2
  lst(a,b)
}
list2env(fun(), envir=.GlobalEnv)#unpacks list key-values to variable-values into the current environment