Ответ 1
Parroting ответ на другую проблему, которая также работает здесь. Не самое прекрасное решение, но варианты по этому работали для меня много раз в прошлом.
Спасибо @Frank для решения без parse()
здесь!
Я хорошо знаком со старой поговоркой "Если ответ - это синтаксический анализ(), вы должны, как правило, переосмыслить вопрос". Но мне сложно придумывать альтернативы много раз, оценивая в data.table
вызывающая среда, мне бы хотелось увидеть надежное решение, которое не выполняет произвольный код, переданный в виде символьной строки. На самом деле половина причин, по которым я отправляю такой ответ, в надежде, что кто-то может порекомендовать лучший вариант.
test_func3 <- function(data, var, var2) {
expr = substitute(sum(var), list(var=as.symbol(var)))
data[, eval(expr)]
}
test_func3(dt, 'x', 'y')
## [1] 5.472968
Быстрая оговорка о гипотетических сценариях конца света возможна с помощью eval (parse (...))
Более подробно подробно обсуждается об опасностях eval(parse(...))
, но я не буду повторять их полностью.
Теоретически у вас могут быть проблемы, если один из ваших столбцов назван чем-то неудачным, например "(system(paste0('kill ',Sys.getpid())))"
(не выполняйте это, он будет убивать вашу сессию R на месте!). Вероятно, этого достаточно, чтобы не потерять сон, если вы не планируете положить это в пакет на CRAN.
Обновление:
Для конкретного случая в комментариях ниже, где таблица сгруппирована, а затем sum
применяется ко всем, .SDcols
потенциально полезна. Единственный способ, которым я знаю, чтобы эта функция возвращала согласованные результаты, даже если dt
имел столбец с именем var3
, должен оценивать аргументы внутри среды функций, но вне среды data.table
, используя c()
.
set.seed(42)
dt <- data.table(
x = rnorm(10),
y = rnorm(10),
z = sample(c("a","b","c"),size = 10, replace = TRUE)
)
test_func3 <- function(data, var, var2, var3) {
ListOfColumns = c(var,var2)
GroupColumn <- c(var3)
dt[, lapply(.SD, sum), by= eval(GroupColumn), .SDcols = ListOfColumns]
}
test_func3(dt, 'x', 'y','z')
возвращает
z x y
1: b 1.0531555 2.121852
2: a 0.3631284 -1.388861
3: c 4.0566838 -2.367558