如何将字符串作为参数传递给需要 R 中的变量的函数
How to pass a string as a parameter to a function which expects a variable in R
第一次调用函数 f 有效,第二次无效。如何将字符串 ("v") 传递给函数 f 以便函数按预期工作?
library(data.table)
f<-function(t,x) t[,deparse(substitute(x)),with=F]
dat<-data.table(v="a")
f(dat,v)
# v
# 1: a
f(dat,eval(parse(text="v")))
# Error in `[.data.table`(t, , deparse(substitute(x)), with = F) :
# column(s) not found: eval(parse(text = "v"))
它将不再是单行的,但您可以测试您传递的内容:
library(data.table)
library(purrr)
dat <- data.table(v="a")
f <- function(dt, x) {
# first, see if 'x' is a variable holding a string with a column name
seval <- safely(eval)
res <- seval(x, dt, parent.frame())
# if it is, then get the value, otherwise substitute() it
if ((!is.null(res$result)) && inherits(res$result, "character")) {
y <- res$result
} else {
y <- substitute(x)
}
# if it's a bare name, then we deparse it, otherwise we turn
# the string into name and then deparse it
if (inherits(y, "name")) {
y <- deparse(y)
} else if (inherits(y, "character")) {
y <- deparse(as.name(x))
}
dt[, y, with=FALSE]
}
f(dat,v)
## v
## 1: a
f(dat, "v")
## v
## 1: a
V <- "v"
f(dat, V)
## v
## 1: a
f(dat, VVV)
#> throws an Error
我将其从 t
切换为 dt
,因为我不喜欢使用内置函数的名称(如 t()
)作为变量名称,除非我真的必须这样做.它可能会在较大的代码块中引入细微的错误,使调试变得令人沮丧。
我还会将 safely()
调用移到 f()
函数之外,以便在您每次 运行 f()
时保存一个函数调用。如果你愿意,你可以使用老式的 try()
,但你必须检查 try-error
,这可能会在某一天中断。您也可以 tryCatch()
包装它,但 safely()
方式对我来说似乎更干净。
第一次调用函数 f 有效,第二次无效。如何将字符串 ("v") 传递给函数 f 以便函数按预期工作?
library(data.table)
f<-function(t,x) t[,deparse(substitute(x)),with=F]
dat<-data.table(v="a")
f(dat,v)
# v
# 1: a
f(dat,eval(parse(text="v")))
# Error in `[.data.table`(t, , deparse(substitute(x)), with = F) :
# column(s) not found: eval(parse(text = "v"))
它将不再是单行的,但您可以测试您传递的内容:
library(data.table)
library(purrr)
dat <- data.table(v="a")
f <- function(dt, x) {
# first, see if 'x' is a variable holding a string with a column name
seval <- safely(eval)
res <- seval(x, dt, parent.frame())
# if it is, then get the value, otherwise substitute() it
if ((!is.null(res$result)) && inherits(res$result, "character")) {
y <- res$result
} else {
y <- substitute(x)
}
# if it's a bare name, then we deparse it, otherwise we turn
# the string into name and then deparse it
if (inherits(y, "name")) {
y <- deparse(y)
} else if (inherits(y, "character")) {
y <- deparse(as.name(x))
}
dt[, y, with=FALSE]
}
f(dat,v)
## v
## 1: a
f(dat, "v")
## v
## 1: a
V <- "v"
f(dat, V)
## v
## 1: a
f(dat, VVV)
#> throws an Error
我将其从 t
切换为 dt
,因为我不喜欢使用内置函数的名称(如 t()
)作为变量名称,除非我真的必须这样做.它可能会在较大的代码块中引入细微的错误,使调试变得令人沮丧。
我还会将 safely()
调用移到 f()
函数之外,以便在您每次 运行 f()
时保存一个函数调用。如果你愿意,你可以使用老式的 try()
,但你必须检查 try-error
,这可能会在某一天中断。您也可以 tryCatch()
包装它,但 safely()
方式对我来说似乎更干净。