【发布时间】:2015-07-17 03:30:39
【问题描述】:
这应该是非常基本的,但我对在 R 中定义函数完全陌生。
有时我想定义一个函数,它只是将一个基本函数包装在一个或多个其他函数中。
例如,我写了prop.table2,它基本上完成了prop.table(table(...))。
我看到的问题是我还希望我的包装函数获取任何子函数的可选参数并适当地传递它们,
例如,
prop.table2(TABLE, useNA = "always", margin = 2) =
prop.table(table(TABLE, useNA = "always"), margin = 2)
完成这样的事情的最简单方法是什么(假设参数名称等没有冲突)?我的基线方法是将每个子函数的所有可选参数简单地粘贴到主函数定义中,即定义:
prop.table2 <- function(..., exclude = if (useNA == "no") c(NA, NaN),
useNA = c("no", "ifany", "always"), dnn = list.names(...),
deparse.level = 1, margin = NULL)
让我们从这个例子开始具体化:
dt <- data.table(id = sample(5, size = 100, replace = TRUE),
grp = letters[sample(4, size = 100, replace=TRUE)])
我想用我的函数复制以下内容:
dt[ , prop.table(table(grp, id, useNA = "always"), margin = 1)]
id
grp 1 2 3 4 5 <NA>
a 0.28571429 0.10714286 0.17857143 0.25000000 0.17857143 0.00000000
b 0.12000000 0.28000000 0.08000000 0.12000000 0.40000000 0.00000000
c 0.23076923 0.23076923 0.15384615 0.19230769 0.19230769 0.00000000
d 0.23809524 0.19047619 0.23809524 0.28571429 0.04761905 0.00000000
<NA>
这就是我现在所处的位置,但它仍然无法正常工作;想法是将所有内容拆分为prop.table 接受的那些参数,然后将其余部分传递给table,但我仍在苦苦挣扎。
prop.table2 <- function(...) {
dots <- list(...)
dots2 <- dots
dots2[intersect(names(dots2), names(formals(prop.table)))] <- NULL
dots3 <- dots2
dots3[intersect(names(dots3), names(formals(table)))] <- NULL
dots2[names(dots2) == ""] <- NULL
prop.table(table(dots3, dots2), margin = list(...)$margin)
}
【问题讨论】:
-
你可以使用列表和do.call,
function(..., prop.param = list()) do.call(prop.table, c(table(...), prop.param)) -
如果子函数共享参数名称会变得复杂。您自己控制传递是最安全的,但这里有一个问题确实检查了函数的形式以查看要传递的参数:stackoverflow.com/questions/25749661/…
-
@baptiste 有错字吗?这对我不起作用,例如:
dt<-data.table(id=sample(10,size=100,rep=T),grp=letters[sample(10,size=100,rep=T)]); dt[,prop.table2(id,grp,prop.param=list(margin=1))] -
@MrFlick 受到您的其他解决方案的启发,我认为类似于
prop.table2<-function(...){prop.table(table(...),margin=list(...)$margin)}的东西会起作用,但我似乎无法解决它——问题似乎在传递“... " 到table -
@MichaelChirico 当您拥有
table(...)时,这会将所有内容传递给表。您不能轻易拆分...s。要么全有,要么全无。
标签: r