Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 如何从返回多个值的函数赋值?_R_Return Value_Variable Assignment_Assign_Multiple Results - Fatal编程技术网

R 如何从返回多个值的函数赋值?

R 如何从返回多个值的函数赋值?,r,return-value,variable-assignment,assign,multiple-results,R,Return Value,Variable Assignment,Assign,Multiple Results,仍然试图进入R逻辑。。。从返回多个值的函数中解包(在LHS上)结果的“最佳”方法是什么 我显然不能这么做: R> functionReturningTwoValues <- function() { return(c(1, 2)) } R> functionReturningTwoValues() [1] 1 2 R> a, b <- functionReturningTwoValues() Error: unexpected ',' in "a," R> c

仍然试图进入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>functionReturningWoValues functionReturningWoValues()
[1] 1 2

R> a,b c(a,b)对你的第二和第三个问题回答是的——这是你需要做的,因为你不能在作业的左边有多个“左值”。这个问题没有正确答案。我真的取决于你对数据做了什么。在上面的简单示例中,我强烈建议:

  • 让事情尽可能简单
  • 只要可能,保持函数矢量化是最佳实践。从长远来看,这提供了最大的灵活性和速度
  • 上面的值1和2有名称是否重要?换句话说,在本例中,为什么将1和2命名为a和b而不仅仅是r[1]和r[2]很重要?在此上下文中需要理解的一件重要事情是,a和b也是长度为1的向量。因此,在赋值过程中,除了有两个不需要引用下标的新向量外,您并没有真正改变任何东西:

    > 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
    
    >r a b类(r)
    [1] “数字”
    >(甲)级
    [1] “数字”
    >a
    [1] 1
    >a[1]
    [1] 1
    
    如果您希望引用字母而不是索引,也可以将名称指定给原始向量:

    > names(r) <- c("a","b")
    > names(r)
    [1] "a" "b"
    > r["a"]
    a 
    1 
    
    >名称(r)名称(r)
    [1] “a”“b”
    >r[“a”]
    A.
    1.
    
    [编辑]鉴于您将分别对每个向量应用最小值和最大值,我建议使用矩阵(如果a和b的长度和数据类型相同)或数据帧(如果a和b的长度相同,但数据类型可能不同),或者使用上一个示例中的列表(如果它们可以具有不同的长度和数据类型)

    >r
    a b
    1 1 5
    2 2 6
    3 3 7
    4 4 8
    >最低(r$a)
    [1] 1
    >最高(南非兰特$b)
    [1] 8
    
    通常我会将输出包装到一个列表中,这非常灵活(输出中可以有数字、字符串、向量、矩阵、数组、列表和对象的任意组合)

    就像:

    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
    

    func2我不知何故在互联网上偶然发现了这个聪明的黑客……我不确定它是肮脏的还是美丽的,但它让你创建了一个“神奇”的操作符,允许你将多个返回值解包到它们自己的变量中。
    :=
    函数,包括以下供后代使用:

    ':=' <- 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)) 
    }
    

    “:=”列表似乎非常适合此用途。例如,在函数中

    x = desired_return_value_1 # (vector, matrix, etc)
    
    y = desired_return_value_2 # (vector, matrix, etc)
    
    returnlist = list(x,y...)
    
    }  # end of function
    
    主程序
    (1)列出[…]使用assign怎么样

    functionReturningTwoValues <- function(a, b) {
      assign(a, 1, pos=1)
      assign(b, 2, pos=1)
    }
    
    如果需要访问现有值,则
    assign
    的相反方式是
    get

    函数returningwovalues[A]
    
    functionReturningTwoValues <- function() { 
      results <- list()
      results$first <- 1
      results$second <-2
      return(results) 
    }
    a <- functionReturningTwoValues()
    
    如果foo和bar中的每一个都是一个数字,那么c(foo,bar)就没有问题;您还可以将这些组件命名为:c(foo=foo,bar=bar)。因此,您可以将结果“res”的组件命名为res[1]、res[2];或者在命名的情况下,命名为res[“foo”]、res[“bar”]

    [乙] 如果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是字符串的向量),这也会很好地工作

    [丙] 如果foo和bar差异很大,不能像上面那样方便地组合,那么您肯定应该返回一个列表

    例如,您的函数可能适合线性模型,并且 还要计算预测值,以便

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

    LM如果要将函数的输出返回到全局环境,可以使用
    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)
    

    要从函数中获取多个输出并将其保持在所需格式,您可以从函数内部将输出保存到硬盘(在工作目录中),然后从函数外部加载它们:

    myfun <- function(x) {
                          df1 <- ...
                          df2 <- ...
                          save(df1, file = "myfile1")
                          save(df2, file = "myfile2")
    }
    load("myfile1")
    load("myfile2")
    

    myfun我用一个R包来解决这个问题。Zeellot包含一个多重赋值或解包赋值操作符,
    %在R3.6.1中,我可以做以下操作

    fr2v <- function() { c(5,3) }
    a_b <- fr2v()
    (a_b[[1]]) # prints "5"
    (a_b[[2]]) # prints "3"
    

    fr2v编辑了这个问题,以便包含您的评论。谢谢。给
    r[1]
    这样的名字可以帮助您把事情弄清楚(好吧,如果像
    a
    这样的名字取而代之,就不需要了).FYI,返回多个值的另一种方法是在返回值上设置一个
    attr
    。这相当于Python的元组解包。此外,我现在更不鼓励使用它,因为该包使用了
    :=
    操作符mucho,更方便:-)我接受了你的答案,因为“with”,但我无法重现您对“list”左侧用法的描述,我得到的只是“object'a'notfound”,它对我有效。您尝试了什么?您阅读了链接帖子并遵循了它吗?您定义了
    list
    [@G.Grothendieck,你介意我把你链接的内容放在你的答案中吗?我想这会让人们更容易使用它。我同意@merlin2011;正如我所写的那样,这种语法似乎嵌入到了R base中。@G.Grothendieck我同意merlin2011和knowah-最好是使用这里重要的实际代码(链接中引用的代码)答案中有。提到结果对象不需要命名列表可能不是一个坏主意。在阅读实际代码之前,这让我困惑了一段时间。正如前面提到的,答案说您需要在链接中运行代码,但大多数人不会立即阅读该代码,除非它直接出现在答案中-这
    
    myfun <- function() list(a = 1, b = 2)
    
    list[a, b] <- myfun()
    a + b
    
    # same
    with(myfun(), a + b)
    
    attach(myfun())
    a + b
    
    functionReturningTwoValues <- function(a, b) {
      assign(a, 1, pos=1)
      assign(b, 2, pos=1)
    }
    
    > functionReturningTwoValues('a', 'b')
    > a
    [1] 1
    > b
    [1] 2
    
    functionReturningTwoValues <- function() { 
      results <- list()
      results$first <- 1
      results$second <-2
      return(results) 
    }
    a <- functionReturningTwoValues()
    
    data.frame(Foo=foo,Bar=bar)
    
    LM<-lm(....) ; foo<-summary(LM); bar<-LM$fit
    
    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")
    
    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, ..)
    
    fr2v <- function() { c(5,3) }
    a_b <- fr2v()
    (a_b[[1]]) # prints "5"
    (a_b[[2]]) # prints "3"