【问题标题】:Return a named list with various elements from function call从函数调用返回一个包含各种元素的命名列表
【发布时间】:2020-04-19 22:58:35
【问题描述】:

问题

我有这样的功能:

myfunc <- function(x){

    a1 = 1
    a2 = c(2,4)
    a3 = data.frame(x = 1:10)
    ...
    an = 'str'
    res = list(a1 = a1,a2 = a2,..., an=an)
    return(res)
}

如我们所见,我用一个命名列表返回我的结果。但是,如果元素的数量很大,我无法一一键入a_i = a_i。我使用下面的代码 sn-p 节省了一半的时间(但我仍然需要在元素名称周围输入",这是浪费时间):

res_short = sapply(c('a1','a2',...,'an'),FUN = function(x){list(get(x))})
return(res_short)

请注意,我的元素名称a1,a2,...,an 中可能不存在模式,我只是使用a1,a2...,an 来简化。 p>

我认为我返回一个命名列表很好,因为列表可以存储不同类型的元素。还有其他方法可以编写我的函数返回吗?我要清晰省时

【问题讨论】:

  • res_short = sapply(paste0("a",1:n),function(x){list(get(x))}) ?
  • 但是如果你必须计算 a1.. an,你可以从 list(a1 =.., a2 = ..., a3 ..) 开始。我错过了什么重要的东西吗?
  • @StupidWolf 感谢您的回复。假设我有 10 个名称复杂的元素,list(a1=..,a2=..) 需要输入两次 'a1',我认为这是浪费时间。
  • R 中不需要return——函数的最后一个表达式就是它的返回值。

标签: r function return apply


【解决方案1】:
  1. mget 如下所示使用mget。要返回所有变量使用mget(ls()) 或返回除x 之外的所有变量使用mget(setdiff(ls(), "x"))ls 不会返回以点开头的对象名称,除非使用了 all 参数,即 ls(all = TRUE),它可用于防止返回某些变量。另一种可能性是使用mgetmode= 参数将返回的对象限制为numeric,例如。见?mget。另一种限制返回对象的方法是在mget 的结果上使用Filter。例如,res &lt;- Filter(is.data.frame, mget(ls())) 只返回数据帧。

    myfunc <- function(x){
        a1 = 1
        a2 = c(2,4)
        a3 = data.frame(x = 1:10)
        an = 'str'
        res = mget(ls(pattern = "^a"))
        return(res)
    }
    myfunc(3) # test
    
  2. 环境 另一种可能性是在执行函数中返回环境。函数中的所有对象(不仅仅是以a 开头的对象)都将在环境中。

    myfunc2 <- function(x) {
        a1 = 1
        a2 = c(2,4)
        a3 = data.frame(x = 1:10)
        an = 'str'
        res = environment()
        return(res)
    }
    out <- myfunc2(3) # test
    out$a
    
  3. 另一种可能性是使用within。只有在内部创建的变量才会被返回。 xwithin 中使用,但未在within 中创建,因此不会返回。

    myfunc3 <- function(x) {
      res <- within(list(), {
       a1 <- x
       a2 <- BOD
      })
      return(res)
    }
    myfunc3(3) # test
    
  4. 多个ls在创建要输出的变量的部分之前和之后执行ls(),然后执行mget差异。

    myfunc4 <- function(x) {
      .excl <- ls()
      a1 <- x
      a2 <- BOD
      res <- mget(setdiff(ls(), .excl))
      return(res)
    }
    myfunc4(3) # test
    

【讨论】:

  • 谢谢!在函数中,变量名应该是有意义的,所以变量名中可能不存在模式。如果元素名称中没有模式,有没有办法解决这个问题?
  • 我不得不承认,我自己过去曾使用过as.list(environment()),但我不喜欢这个解决方案,它没有纪律性。我宁愿代码明确它返回的变量。 mget 因此更好。
  • 已将我的 cmets 移至答案。
【解决方案2】:

如果我理解正确,您的要求非常灵活。您有一堆名称没有模式的变量。您想对每个变量应用不同的计算。好吧,您意识到您确实需要至少输入一次所有内容。一种方法是列出所有可能的变量名称及其计算。然后,您可以将所有这些或一个子集应用于您的输入。以下是 3 个名称和 3 种不同计算的示例。

mycomputer = list(
    add5 = function(x) {
        x + 5
    },
    mymean = function(x) {
        mean(x)
    },
    square = function(x) {
        x*x
    }
)
computeall = function(x) {
    result = lapply(names(mycomputer), function(f) {
        mycomputer[[f]](x)
    })
    names(result) = names(mycomputer)
    result
}

computeall(c(1,2,3))
## $add5
## [1] 6 7 8
## 
## $mymean
## [1] 2
## 
## $square
## [1] 1 4 9

【讨论】:

  • 感谢您的回复!我想要的是从函数调用返回一个命名列表。每个元素都有不同的名称和类型。如果元素很多,输入它们的名称是浪费时间。但是,您的解决方案是在一个输入上应用多个功能。也许是我蹩脚的英语误导了你,对不起
  • 在我的示例中,您将数据传递给函数 computeall() 并返回一个命名列表。此时无需重新输入名称。在函数 mycomputer() 中一次性输入名称。不知道这和你问的有什么不同。
猜你喜欢
  • 2021-12-09
  • 1970-01-01
  • 2021-07-16
  • 2022-12-04
  • 1970-01-01
  • 1970-01-01
  • 2021-01-23
  • 1970-01-01
  • 2017-06-14
相关资源
最近更新 更多