在编写自己的函数时如何使用R的省略号功能? [英] How to use R's ellipsis feature when writing your own function?

查看:1378
本文介绍了在编写自己的函数时如何使用R的省略号功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

R语言有一个很好的功能来定义函数,它可以带有可变数量的参数。例如,函数 data.frame 可以使用任意数量的参数,每个参数都会成为结果数据表中列的数据。用法示例:

 > data.frame(letters = c(a,b,c),numbers = c(1,2,3),notes = c(do,re,mi))
字母数字笔记
1 a 1 do
2 b 2 re
3 c 3 mi

函数的签名包含一个省略号,如下所示:

  function(...,row .names = NULL,check.rows = FALSE,check.names = TRUE,
stringsAsFactors = default.stringsAsFactors())
{
[函数定义]
}

我想编写一个类似的函数,取多个值并将它们合并成一个返回值(以及做一些其他处理)。为了做到这一点,我需要弄清楚如何从函数的函数参数中解开 ... 。我不知道该怎么做。 data.frame 的函数定义中的相关行是 object< - as.list(substitute(list(...)))[ -1L] ,这是我无法理解的。



那我该如何将函数签名中的省略号转换为例如,一个列表?



更具体地说,我如何在下面的代码中编写 get_list_from_ellipsis

  my_ellipsis_function(...){
input_list< - get_list_from_ellipsis(...)
output_list< - lapply(X = input_list,FUN = do_something_interesting)
return(output_list)
}

my_ellipsis_function(a = 1:10,b = 11:20,c = 21: 30)






编辑



似乎有两种可能的方式来做到这一点。它们是 as.list(substitute(list(...)))[ - 1L] list(...)。但是,这两者并不完全一样。 (有关差异,请参阅答案中的示例。)任何人都可以告诉我它们之间的实际区别是什么,以及我应该使用哪一个? 解决方案我看到了答案和评论,我发现有几件事没有提到:


  1. data.frame 使用 list(...)版本。代码片段:

      object<  -  as.list(substitute(list(...)))[ -  1L ] 
    mrn< - is.null(row.names)
    x< - list(...)

    object 被用来做列名的魔术,但是使用 x 创建最终的 data.frame

    使用未评估的 ... 参数 write.csv 代码其中 match.call 被使用。


  2. 当你在评论结果中写Dirk答案不是列表列表。是长度为4的列表,其元素是 language type。第一个对象是符号 - list ,第二个是表达式 1:10 等等。这解释了为什么需要 [ - 1L] :它从中提供的参数中移除了预期的符号 ... (因为它总是一个列表)。
    如Dirk所述替代返回parse tree未评估的表达式。
    当您调用 my_ellipsis_function(a = 1:10,b = 11:20,c = 21:30),则 ... created参数列表: list(a = 1:10,b = 11:20,c = 21:30)替换使它成为一个包含四个元素的列表:

      List of 4 
    $:符号列表
    $ a:语言1:10
    $ b:语言11:20
    $ c:语言21:30
    code>

    第一个元素没有名称,这是 [[1]]

      my_ellipsis_function<  -  function(...){
    input_list< - as .list(substitute(list(...)))
    str(input_list)
    NULL
    }
    my_ellipsis_function(a = 1:10,b = 11:20,c = 21:30)


  3. 如上所述,我们可以使用 str 来检查函数中的对象。

      my_ellipsis_function<  -  function(...){ 
    input_list< - list(...)
    output_list< - lapply(X = input_list,function(x){str(x); summary(x)})
    return output_list)
    }
    my_ellipsis_function(a = 1:10,b = 11:20,c = 21:30)
    int [1:10] 1 2 3 4 5 6 7 8 9 10
    int [1:10] 11 12 13 14 15 16 17 18 19 20
    int [1:10] 21 22 23 24 25 26 27 28 29 30
    $ a
    分钟。第一曲。中位数均值3曲。最大。
    1.00 3.25 5.50 5.50 7.75 10.00

    $ b最小。第一曲。中位数均值3曲。最大。
    11.0 13.2 15.5 15.5 17.8 20.0
    $ c
    最小值第一曲。中位数均值3曲。最大。
    21.0 23.2 25.5 25.5 27.8 30.0

    没关系。让我们看看替换版本:

      my_ellipsis_function<  -  function(.. 。){
    input_list< - as.list(substitute(list(...)))
    output_list< - lapply(X = input_list,function(x){str(x); summary (x)})
    return(output_list)
    }
    my_ellipsis_function(a = 1:10,b = 11:20,c = 21:30)
    符号列表
    语言1:10
    语言11:20
    语言21:30
    [[1]]
    长度类模式
    1名称名称
    $ a
    长度班级模式
    3呼叫电话

    $ b长度班级模式
    3呼叫电话
    $ c
    长度班级模式
    3 call call

    不是我们所需要的。您需要额外的技巧来处理这些对象(如 write.csv )。


如果你想使用 ... 那么你应该在Shane答案中使用它,由 list(。 ..)


The R language has a nifty feature for defining functions that can take a variable number of arguments. For example, the function data.frame takes any number of arguments, and each argument becomes the data for a column in the resulting data table. Example usage:

> data.frame(letters=c("a", "b", "c"), numbers=c(1,2,3), notes=c("do", "re", "mi"))
  letters numbers notes
1       a       1    do
2       b       2    re
3       c       3    mi

The function's signature includes an ellipsis, like this:

function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, 
    stringsAsFactors = default.stringsAsFactors()) 
{
    [FUNCTION DEFINITION HERE]
}

I would like to write a function that does something similar, taking multiple values and consolidating them into a single return value (as well as doing some other processing). In order to do this, I need to figure out how to "unpack" the ... from the function's arguments within the function. I don't know how to do this. The relevant line in the function definition of data.frame is object <- as.list(substitute(list(...)))[-1L], which I can't make any sense of.

So how can I convert the ellipsis from the function's signature into, for example, a list?

To be more specific, how can I write get_list_from_ellipsis in the code below?

my_ellipsis_function(...) {
    input_list <- get_list_from_ellipsis(...)
    output_list <- lapply(X=input_list, FUN=do_something_interesting)
    return(output_list)
}

my_ellipsis_function(a=1:10,b=11:20,c=21:30)


Edit

It seems there are two possible ways to do this. They are as.list(substitute(list(...)))[-1L] and list(...). However, these two do not do exactly the same thing. (For differences, see examples in the answers.) Can anyone tell me what the practical difference between them is, and which one I should use?

解决方案

I read answers and comments and I see that few things weren't mentioned:

  1. data.frame uses list(...) version. Fragment of the code:

    object <- as.list(substitute(list(...)))[-1L]
    mrn <- is.null(row.names)
    x <- list(...)
    

    object is used to do some magic with column names, but x is used to create final data.frame.
    For use of unevaluated ... argument look at write.csv code where match.call is used.

  2. As you write in comment result in Dirk answer is not a list of lists. Is a list of length 4, which elements are language type. First object is a symbol - list, second is expression 1:10 and so on. That explain why [-1L] is needed: it removes expected symbol from provided arguments in ... (cause it is always a list).
    As Dirk states substitute returns "parse tree the unevaluated expression".
    When you call my_ellipsis_function(a=1:10,b=11:20,c=21:30) then ... "creates" a list of arguments: list(a=1:10,b=11:20,c=21:30) and substitute make it a list of four elements:

    List of 4
    $  : symbol list
    $ a: language 1:10
    $ b: language 11:20
    $ c: language 21:30
    

    First element doesn't have a name and this is [[1]] in Dirk answer. I achieve this results using:

    my_ellipsis_function <- function(...) {
      input_list <- as.list(substitute(list(...)))
      str(input_list)
      NULL
    }
    my_ellipsis_function(a=1:10,b=11:20,c=21:30)
    

  3. As above we can use str to check what objects are in a function.

    my_ellipsis_function <- function(...) {
        input_list <- list(...)
        output_list <- lapply(X=input_list, function(x) {str(x);summary(x)})
        return(output_list)
    }
    my_ellipsis_function(a=1:10,b=11:20,c=21:30)
     int [1:10] 1 2 3 4 5 6 7 8 9 10
     int [1:10] 11 12 13 14 15 16 17 18 19 20
     int [1:10] 21 22 23 24 25 26 27 28 29 30
    $a
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
       1.00    3.25    5.50    5.50    7.75   10.00 
    $b
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
       11.0    13.2    15.5    15.5    17.8    20.0 
    $c
       Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
       21.0    23.2    25.5    25.5    27.8    30.0 
    

    It's ok. Lets see substitute version:

       my_ellipsis_function <- function(...) {
           input_list <- as.list(substitute(list(...)))
           output_list <- lapply(X=input_list, function(x) {str(x);summary(x)})
           return(output_list)
       }
       my_ellipsis_function(a=1:10,b=11:20,c=21:30)
        symbol list
        language 1:10
        language 11:20
        language 21:30
       [[1]]
       Length  Class   Mode 
            1   name   name 
       $a
       Length  Class   Mode 
            3   call   call 
       $b
       Length  Class   Mode 
            3   call   call 
       $c
       Length  Class   Mode 
            3   call   call 
    

    Isn't what we needed. You will need additional tricks to deal with these kind of objects (as in write.csv).

If you want use ... then you should use it as in Shane answer, by list(...).

这篇关于在编写自己的函数时如何使用R的省略号功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆