Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 使用表达式作为参数分派S4方法_R_Expression_Dispatch_S4 - Fatal编程技术网

R 使用表达式作为参数分派S4方法

R 使用表达式作为参数分派S4方法,r,expression,dispatch,s4,R,Expression,Dispatch,S4,我试图说服S4方法使用表达式作为参数,但我总是得到一个返回的错误。一个简单的例子说明了我在这里要做的事情: setGeneric('myfun',function(x,y)standardGeneric('myfun')) setMethod('myfun',c('data.frame','expression'), function(x,y) transform(x,y) ) 如果我现在尝试: > myfun(iris,NewVar=Petal.Width*Pet

我试图说服S4方法使用表达式作为参数,但我总是得到一个返回的错误。一个简单的例子说明了我在这里要做的事情:

setGeneric('myfun',function(x,y)standardGeneric('myfun'))

setMethod('myfun',c('data.frame','expression'),
          function(x,y) transform(x,y) )
如果我现在尝试:

> myfun(iris,NewVar=Petal.Width*Petal.Length)
Error in myfun(iris, NewVar = Petal.Width * Petal.Length) : 
  unused argument(s) (NewVar = Petal.Width * Petal.Length)

> myfun(iris,{NewVar=Petal.Width*Petal.Length})
Error in myfun(iris, list(NewVar = Petal.Width * Petal.Length)) : 
 error in evaluating the argument 'y' in selecting a method for 
 function 'myfun': Error: object 'Petal.Width' not found
如果我理解正确的话,这些参数似乎已经在泛型中进行了评估。因此,将表达式传递给方法至少看起来很棘手。是否可以使用表达式来使用S4分派方法



编辑:更改为transform,因为这是一个更好的示例。

它不是S4,也不是参数计算,而是R无法判断您是要传递命名参数还是表达式的形式为a=b

如果查看“within”的帮助,它会使用大括号确保表达式被解析为表达式

我还认为在函数内部调用不会替换函数的调用者

我还认为我对表达式了解得不够。

您已经在这个示例方法中将“expression”指定为第二个参数的类。第一个示例返回一个错误,因为

NewVar=Petal.Width*Petal.Length
正在被解释为myfun的带值命名参数

Petal.Width*Petal.Length
因为NewVar不是此方法或泛型的参数,所以没有机会进行计算

在第二个示例中,我不确定闭合的大括号是怎么回事,因为我的错误与所示的不同:

myfun(iris,{: 为函数“myfun”选择方法时计算参数“y”时出错:错误:找不到对象“Petal.Width”

但是,当我强制您的表达式成为表达式对象时,我没有收到任何错误,并将iris data.frame作为输出:

myfun(iris, expression(NewVar=Petal.Width*Petal.Length))
我认为这只是部分回答了您的问题,因为简单地返回iris data.frame并不是您想要的。transform()没有正确计算表达式。我怀疑您希望输出与以下硬编码版本的输出完全匹配:

transform(iris, NewVar=Petal.Width*Petal.Length)
下面是一个使用eval计算表达式的简短示例

z <- expression(NewVar = Petal.Width*Petal.Length)
test <- eval(z, iris)
head(test, 2)
同样,这个实现本质上是硬编码的,即只有一个变量列将被添加到输入data.frame中,尽管该变量列的名称和表达式是任意的,并且作为表达式提供。我确信有一个更好、更一般的答案,它将计算y中的表达式,就像它是w一样在transform()函数中没有直接调用,但我现在不知道应该使用什么作为表达式()的适当“逆”函数

如果您实际上不想在y上发送,则始终存在标准…:

setGeneric('myfun', function(x, ...) standardGeneric('myfun'))
setMethod('myfun', 'data.frame', function(x, ...){
    transform(x, ...)
})
这很有效。但是你的问题是关于在表达式对象上实际调度

以下方法不起作用,但我认为它正在变得越来越近。也许有人可以加入进来并进行一些最后的调整:

setGeneric('myfun', function(x, y) standardGeneric('myfun'))
setMethod('myfun',c('data.frame', 'expression'), function(x, y){
    transform(x, eval(y, x, parent.frame()))
})
## try out the new method
z <- expression(NewVar = Petal.Width*Petal.Length)
test <- myfun(iris, z)
names(test)
完整的示例如下所示:

setGeneric('myfun', function(x, y) standardGeneric('myfun'))
setMethod('myfun',c('data.frame', 'expression'), function(x, y){
    do.call("transform", c(list(x), as.list(y)))
})
# try out the new method
z <- expression(NewVar = Petal.Width*Petal.Length)
test <- myfun(iris, z)
names(test)
[1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"     
[6] "NewVar"
setGeneric('myfun',函数(x,y)standardGeneric('myfun'))
setMethod('myfun',c('data.frame','expression'),函数(x,y){
调用(“transform”,c(list(x),as.list(y)))
})
#试试新方法

z不只是因为
expr
是一个多行表达式(在多个表达式的意义上)才使用大括号吗?在()
如果你只提供一个R表达式。你关于命名参数或表达式的观点很有趣。现在是不是
=
@Gavin:我同意,inthein的不等式是一个愚蠢的例子。我用transform来说明,但问题确实出在调度中。表达式似乎是在dispat之前计算的ching发生了,我不知道如何关闭它…你试过用大括号括起来吗?这可能会防止类似的“解析错误”?可能无法解决你的问题,但可能会有所帮助。@Nick:我做到了。它所带来的帮助是DWin说的:它在调度时得到评估。我试着用match.call()提取它,但我无法将其转换。请参阅SfDA第399-402页,钱伯斯在其中描述了为什么必须对任何经过签名测试的论点进行评估。@DWin:愿意分享一个链接吗?SfDA对我来说听起来很陌生,我想你不是在说国家食品药品监督管理局……对不起。“数据分析软件”约翰·钱伯斯(John Chambers)。作为补充,我注意到您的签名值与参数名称没有关联,而在示例中是格式。(注意:您还没有在问题正文中更改为
transform
)。我认为您混淆了表达式的两种用法-表达式创建的对象(您可以分派)与从惰性参数表达式(您无法分派)捕获未赋值的承诺@hadley:thx进行查看。我对
expression()
as.expression()
做了大量实验。expression()
并没有真正帮助我。唉,试图从
match.call()获取表达式
,但我也没有得到任何进一步的解释。想进一步阐述一下表达式的两种用法之间的区别吗?当你有嵌套函数时,eval会带来一系列全新的问题。环境…我知道我可以硬编码它,但关键是要有转换的灵活性,但我自己的S4对象除外。我解决了它使用S3方法,但我对屏幕后面发生的事情特别感兴趣……是的,我发现eval也存在同样的问题。我认为我附加的do.call方法可能会解决您的问题。
setGeneric('myfun', function(x, y) standardGeneric('myfun'))
setMethod('myfun',c('data.frame', 'expression'), function(x, y){
    transform(x, eval(y, x, parent.frame()))
})
## try out the new method
z <- expression(NewVar = Petal.Width*Petal.Length)
test <- myfun(iris, z)
names(test)
do.call()
setGeneric('myfun', function(x, y) standardGeneric('myfun'))
setMethod('myfun',c('data.frame', 'expression'), function(x, y){
    do.call("transform", c(list(x), as.list(y)))
})
# try out the new method
z <- expression(NewVar = Petal.Width*Petal.Length)
test <- myfun(iris, z)
names(test)
[1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"     
[6] "NewVar"