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

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

问题描述

R 语言有一个很好的特性,用于定义可以接受可变数量参数的函数.例如,函数 data.frame 接受任意数量的参数,每个参数成为结果数据表中某一列的数据.示例用法:

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]
}

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

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?

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

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)


编辑

似乎有两种可能的方法可以做到这一点.它们是 as.list(substitute(list(...)))[-1L]list(...).然而,这两者并不完全相同.(有关差异,请参阅答案中的示例.)谁能告诉我它们之间的实际区别是什么,我应该使用哪一个?


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 使用 list(...) 版本.代码片段:

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

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

object 用于对列名做一些魔术,但 x 用于创建最终的 data.frame.
要使用未评估的 ... 参数,请查看使用 match.callwrite.csv 代码.

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.

正如您在 Dirk 中的评论结果中所写,答案不是列表列表.是一个长度为4的列表,其中元素是language类型.第一个对象是 symbol - list,第二个是表达式 1:10 等等.这解释了为什么需要 [-1L] :它从 ... 中提供的参数中删除了预期的 symbol (因为它总是一个列表).
正如 Dirk 所说,substitute 返回解析树未求值的表达式".
当您调用 my_ellipsis_function(a=1:10,b=11:20,c=21:30) 时,...创建"一个参数列表:list(a=1:10,b=11:20,c=21:30)substitute 使其成为包含四个元素的列表:

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

第一个元素没有名称,这是 Dirk 答案中的 [[1]].我使用以下方法实现了此结果:

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)

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

  • 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 
    

    没关系.让我们看看 substitute 版本:

    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 
    

    这不是我们需要的.您将需要额外的技巧来处理这些类型的对象(如在 write.csv 中).

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

    如果你想使用 ... 那么你应该像在 Shane 答案中一样使用它,通过 list(...).

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

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

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