我试图在我写的另一个函数中包含对np::npcdensbw()
的调用。因此,我希望能够将条件密度的公式作为变量传递给npcdensbw()
。但是,当我这样做时,我得到一个错误,我无法弄清楚为什么。最小的例子:
####### Testing data
N <- 100 # sample size
x_cont <- rnorm(N)
x_dis <- rbinom(N, 1, .5)
# errors
e <- rnorm(N)
# depvar
y <- as.numeric((x_cont + .5 * x_dis + e) > 0)
df <- data.frame(y, x_cont, x_dis)
当我编写公式并直接调用函数时,它执行没有问题:
# Estimate conditional density of y
ycdens <- np::npcdensbw(as.factor(y) ~ x_cont + as.factor(x_dis), df)
但是因为我想从另一个函数中调用这个函数,我需要将公式作为参数传递,当我这样做时它不起作用:
# create formula object
f <- formula(as.factor(y) ~ x_cont + as.factor(x_dis))
ycdens2 <- np::npcdensbw(f, df) # doesnt work
#> Error in names(res) <- c("response", "terms"): 'names' attribute [2] must be the same length as the vector [1]
ycdens2 <- np::npcdensbw(deparse(f), df) # doesnt work
#> Error in npcdensbw.conbandwidth(xdat = xdat, ydat = ydat, bws = tbw): number of rows of 'ydat' does not match 'xdat'\
func <- function(form, data) {
np::npcdensbw(form, data)
}
func(as.factor(y) ~ x_cont + as.factor(x_dis), df) # doesnt work
# Error in names(res) <- c("response", "terms") : 'names' attribute [2] must be the same length as the vector [1]
我似乎无法弄清楚为什么会发生这种情况或我如何规避它。在函数中使用时出现的错误似乎来自我在explodeFormula()
github page上找到的代码函数np
,并且只是:
explodeFormula <- function(formula){
res <- strsplit(strsplit(paste(deparse(formula), collapse=""),
" *[~] *")[[1]], " *[+] *")
stopifnot(all(sapply(res,length) > 0))
names(res) <- c("response","terms")
res
}
当我在任意公式上调用它时,此代码不会抛出错误,因此问题必须在其他地方。
答案 0 :(得分:1)
遗憾的是,此功能的编码方式无法轻易传递变量。
查看npcdensbw.formula()
,它会在调用match.call
之前执行explodeFormula()
,因为它已经崩溃了(正如您已正确指出的那样)。
这意味着deparse(formula)
只是您在通话中传递的变量(字符串),例如上面例子中的"f"
或"form"
。
如果explodeFormula()
的代码改为调用deparse(eval(formula))
,则可能会有效。
简单示例:
explodeFormula <- function(formula) {
res <- strsplit(strsplit(paste(deparse(formula), collapse=""),
" *[~] *")[[1]], " *[+] *")
stopifnot(all(sapply(res,length) > 0))
names(res) <- c("response","terms")
res
}
myFunc <- function(x, ...) {
mf <- match.call(expand.dots = FALSE)
explodeFormula(mf[["x"]])
}
ff <- as.factor(y) ~ x_cont + as.factor(x_dis)
myFunc(ff)
myFunc(as.factor(y) ~ x_cont + as.factor(x_dis))
explodeFormula <- function(formula) {
res <- strsplit(strsplit(paste(deparse(eval(formula)), collapse=""), " *[~] *")[[1]], " *[+] *")
stopifnot(all(sapply(res,length) > 0))
names(res) <- c("response","terms")
res
}
myFunc(ff)
$response
[1] "as.factor(y)"
$terms
[1] "x_cont" "as.factor(x_dis)"