编写自己的函数时如何使用 R 的省略号功能? [英] How to use R's ellipsis feature when writing your own function?
问题描述
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:
data.frame
使用list(...)
版本.代码片段:
data.frame
useslist(...)
version. Fragment of the code:
object <- as.list(substitute(list(...)))[-1L]
mrn <- is.null(row.names)
x <- list(...)
object
用于对列名做一些魔术,但 x
用于创建最终的
要使用未评估的 ...
参数,请查看使用 match.call
的 write.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屋!