Как передать строку в качестве параметра функции, которая ожидает переменную в R
Первый вызов функции f работает, второй - нет. Как я могу передать String ("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"))
1 ответ
Это больше не будет однострочно, но вы можете проверить, что вы передаете:
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()
путь мне кажется чище.