Как передать строку в качестве параметра функции, которая ожидает переменную в 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() путь мне кажется чище.

Другие вопросы по тегам