Мне интересно, можно ли заменить выражения в часть i data.table. Я настроил глубоко вложенный список, который содержит предустановленные параметры для выполнения поднастройки в зависимости от того, какую подгруппу выбрал пользователь в блестящем приложении. Я подозреваю, что это невозможно, но надеюсь получить подтверждение так или иначе.
Если это невозможно, я приветствую любые идеи альтернативных решений.
Базовый пример
library(data.table)
dt = data.table(
y = rep(c('a','b'),5),
x = 1:10
)
exp1 = "x > 5"
dt[y == "a" & substitute(exp1)]
# Error: operations are possible only for numeric, logical or complex types
@jangorecki новый аргумент env в настоящее время доступен только в версии для разработчиков. В CRAN-версии 1.14.8 этой функции еще не было.
Да, я знаю, просто запустите data.table::update_dev_pkg()
@jangorecki - я знаю о новом аргументе env и хочу, чтобы это был жизнеспособный вариант. Тем не менее, блестящее приложение, над которым я работаю, является частью большой группы приложений, управляемых одной и той же renv настройкой. Поэтому я очень осторожно отношусь к использованию версии dev любого пакета в производстве.





Можно использовать eval(parse(..)), но есть некоторые проблемы, связанные с этим.
library(data.table)
exp1 = "x > 5"
dt[y == "a" & eval(parse(text = exp1))]
# y x
#1: a 7
#2: a 9
у eval(str2lang(expr1)) тоже есть проблемы? или даже eval(str2expression(expr1))
Хм ... Я не использовал их, поэтому я не уверен.
@Onyambu eval(parse(..)), eval(str2lang(expr1)) и eval(str2expression(expr1)) требуют, чтобы выражения строились путем манипуляций со строками (объединение, замена...), а затем анализировались. У авторов data.table есть довольно хорошее резюме о его проблемах.
Мой подход таков:
library(data.table)
exp1 = "x > 5" |> str2lang()
(ll <- substitute(
dt[y == "a" & e1],
list(
e1 = exp1
)
))
eval(ll)
Я думаю, что это хороший подход, потому что он поддерживает идиоматический вид data.table. Например, если вы хотите dt[y == "a" & x > 5, .(mm = length(x)), by = "y"]:
(ll <- substitute(
dt[y == "a" & e1, .(mm = f1(e2)), by = e3], # Change right here and maintain data.table's look
list(
e1 = exp1,
# e1 = "x > 5" |> str2lang(),
e2 = quote(x), # Allow more flexibilities
e3 = "y", # Allow more flexibilities
f1 = quote(length) # Allow more flexibilities
)
))
eval(ll)
Это также похоже на подходы substitute2 и env, предложенные в разрабатываемой версии data.table.
Да, env arg просто оборачивает i, j, by в подстановочные вызовы
Потрясающе, спасибо за это! Не могли бы вы объяснить во втором примере необходимость добавления quote вместо e2 и f1. Или отошлите меня к какой-нибудь документации по этому поводу?
@ Джейми Извините за поздний ответ. Без quote в e2 оно станет e2 = x. Это станет случаем e1 (т. Е. Найдите где-нибудь эту переменную x и подставьте значение переменной x в e2). Попробуйте x <- 3; (ll <- substitute(dt[y == "a" & e1, .(mm = f1(e2)), by = e3], list(e1 = "x > 5" |> str2lang(), e2 = x, e3 = "y", f1 = quote(length)))), результат dt[y == "a" & x > 5, .(mm = length(3)), by = "y"]
Кроме того, вы можете использовать e2 = as.name("x") вместо e2 = quote(x). В этом случае облегчает интерпретацию то, что нам нужно имя/символ x, а не значение x.
Канонические ресурсы для этого: Руководства по R-Определение языка R-Вычисления на языке и help(quote), help(expression), help(parse)...
Не используйте анализ eval. Используйте новый аргумент env в data.table, который был создан именно для решения таких проблем, как ваша. Подробнее об этом можно прочитать в новой виньетке rdatatable.gitlab.io/data.table/articles/…