nac*_*hti 13 r substitution data.table
如果我想将函数的参数解析为错误或警告,如果参数转换为函数中的data.table,则会发生奇怪的事情:
e <- data.frame(x = 1:10)
### something strange is happening
foo <- function(u) {
u <- data.table(u)
warning(deparse(substitute(u)), " is not a data.table")
u
}
foo(e)
## foo(e)
## x
## 1: 1
## 2: 2
## 3: 3
## 4: 4
## 5: 5
## 6: 6
## 7: 7
## 8: 8
## 9: 9
## 10: 10
## Warning message:
## In foo(e) :
## structure(list(x = 1:10), .Names = "x", row.names = c(NA, -10L), class = c("data.table", "data.frame"), .internal.selfref = <pointer: 0x10026568>) is not a data.table
Run Code Online (Sandbox Code Playgroud)
如果我在data.table一切正常之前解密它:
### ok
foo1 <- function(u) {
nu <- deparse(substitute(u))
u <- data.table(u)
warning(nu, " is not a data.table")
u
}
## foo1(e)
## x
## 1: 1
## 2: 2
## 3: 3
## 4: 4
## 5: 5
## 6: 6
## 7: 7
## 8: 8
## 9: 9
## 10: 10
## Warning message:
## In foo1(e) : e is not a data.table
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果e已经是一个data.table或没有差异.我故意找到它,当我分析一些代码时,这里deparse非常耗时,因为e它非常大.
这里发生了什么,我该如何处理data.frame和data.table输入这些功能?
nachti
Bro*_*ieG 15
这是因为substitute当您处理普通变量而不是promise对象时,行为会有所不同.promise对象是一个形式参数,并且有一个特殊的插槽,其中包含生成它的表达式.换句话说,promise对象是函数中的变量,该函数是该函数的参数列表的一部分.当您substitute在函数中使用promise对象时,它将在对分配给该正式参数的函数的调用中检索表达式.来自?substitute:
通过检查解析树的每个组件进行替换,如下所示:如果它不是env中的绑定符号,则它将保持不变.如果它是一个promise对象,即函数的形式参数或使用delayedAssign()显式创建的,则promise的表达式槽替换该符号.如果它是普通变量,则其值被替换,除非env是.GlobalEnv,在这种情况下符号保持不变.
在您的情况下,您实际上使用新的变量覆盖原始的promise变量:
u <- data.table(u)
Run Code Online (Sandbox Code Playgroud)
此时u成为包含数据表的普通变量.当你substitute在u这个点之后,substitute刚刚返回的数据表,它deparse处理回,将产生它,这就是为什么它是缓慢的R语言.
这也解释了为什么你的第二个例子有效.你substitute虽然变量仍然是一个承诺(即在你覆盖之前u).这也是你第二个问题的答案.在覆盖您的承诺之前要么替换,要么不覆盖您的承诺.
有关更多详细信息,请参阅我在此处摘录的R语言定义(承诺)的第2.1.8节:
Promise对象是R的懒惰评估机制的一部分.它们包含三个槽:值,表达式和环境.调用函数时,参数匹配,然后每个形式参数都绑定到一个promise.为该形式参数提供的表达式和调用该函数的环境的指针存储在promise中.