我正在尝试编写一个函数:
myfunc <- function(df, out, ...) { # ... = variables in a dataframe
df <- arrange(df, ...) # plyr function that orders rows
out <- df[!duplicated(df[,c(...)]),] # remove duplicates
}
我无法弄清楚如何让第三一行发挥作用。只需要将“...”参数转换为字符串向量,以便!duplicated()函数可以正常工作。
我知道 deparse(substitute(x))适用于1个参数:
> foo <- function(x) deparse(substitute(x))
> foo(bar)
[1] "bar"
但它不适用于多个参数。如何更改它以便多个参数起作用?
> foo <- function(...) deparse(substitute(...))
> foo(bar,goo,poo)
[1] "bar" "goo" "poo"
我还欢迎修改原始函数(myfunc)的其他解决方案,如果这样可以更容易。感谢。
答案 0 :(得分:2)
由于被替换的表达式仍然是表达式,因此deparse(substitute())不起作用,并且希望各个元素都是变量。诀窍是将省略号转换为列表,然后替换以获取其元素作为表达式,最后解析表达式树中的每个元素:
ellipsis_to_vector <- function(...) {
# Convert to a list, but with the variables still as an expression
args_as_expression = substitute(list(...))
# Deparse each item in the expression, turning it into a char vector
# Why the [-1]? Because the first element in the list expression is "list"! :-)
args_as_char_vector = sapply(args_as_expression,deparse)[-1]
args_as_char_vector
}
ellipsis_to_vector(this, and, that)
#> [1] "this" "and" "that"
ellipsis_to_vector(single)
#> [1] "single"
ellipsis_to_vector() # Works for empty ellipsis as well
#> character(0)
答案 1 :(得分:1)
我认为match.call
在这种情况下会更适合你。观察
foo <- function(df, ...) {
mycall<-as.list(match.call())
cols<-sapply(mycall[-(1:2)], deparse)
df<-arrange(df, ...)
df[!duplicated(df[, cols]),]
}
#test data
set.seed(15)
dd<-data.frame(a=1:20,
b=sample(1:50, 20, replace=T),
c=sample(1:50, 20, replace=T)
)
dd <-rbind(dd, cbind(a=21:24, dd[9:12, 2:3])) # add dups
dd <-dd[sample.int(nrow(dd)),] #shuffle
#try out function
out<-foo(dd, b,c)
out
我离开out
,因为你真的应该在函数之外分配结果,否则在函数调用完成后对变量的更改会消失。