Прежде всего: благодаря @MattDowle; data.table
- одна из лучших вещей, которые
когда-либо случалось со мной, так как я начал использовать R
.
Во-вторых: мне известно много обходных решений для различных вариантов использования столбца переменной
имена в data.table
, включая:
- Выберите/назначьте переменные data.table, имена которых хранятся в символьном векторе
- передать имя столбца в data.table с использованием переменной в R
- Обращение к столбцам data.table именами, сохраненными в переменных
- передача имен столбцов в data.table программно
- Мета-программирование Data.table
- Как написать функцию, вызывающую функцию, которая вызывает data.table?
- Использование динамических имен столбцов в` data.table`
- динамические имена столбцов в data.table, R
- Назначьте несколько столбцов, используя: = в data.table, по группе
- Установка имени столбца в "group by" работа с таблицей data.table
- R, суммируя несколько столбцов с data.table
и, возможно, больше я не ссылался.
Но: даже если бы я узнал все трюки, описанные выше, до такой степени, что я никогда не приходилось искать их, чтобы напомнить себе, как их использовать, я все равно найду что работа с именами столбцов, которые передаются как параметры функции, чрезвычайно утомительная задача.
То, что я ищу, является альтернативой, одобренной лучшей практикой к следующему обходному пути/рабочему процессу. Рассматривать что у меня есть куча столбцов похожих данных, и я хотел бы выполнить последовательность подобных операций над этими столбцами или наборами из них, где операции имеют произвольно высокую сложность, а группы имен столбцов передаются каждой операции, указанной в Переменная.
Я понимаю, что эта проблема звучит надуманно, но я сталкиваюсь с ней с удивительной частотой. Примеры обычно настолько беспорядочны, что трудно отделить функции, относящиеся к этому вопросу, но я недавно наткнулся на тот, который был достаточно простым для упрощения для использования в качестве MWE здесь:
library(data.table)
library(lubridate)
library(zoo)
the.table <- data.table(year=1991:1996,var1=floor(runif(6,400,1400)))
the.table[,`:=`(var2=var1/floor(runif(6,2,5)),
var3=var1/floor(runif(6,2,5)))]
# Replicate data across months
new.table <- the.table[, list(asofdate=seq(from=ymd((year)*10^4+101),
length.out=12,
by="1 month")),by=year]
# Do a complicated procedure to each variable in some group.
var.names <- c("var1","var2","var3")
for(varname in var.names) {
#As suggested in an answer to Link 3 above
#Convert the column name to a 'quote' object
quote.convert <- function(x) eval(parse(text=paste0('quote(',x,')')))
#Do this for every column name I'll need
varname <- quote.convert(varname)
anntot <- quote.convert(paste0(varname,".annual.total"))
monthly <- quote.convert(paste0(varname,".monthly"))
rolling <- quote.convert(paste0(varname,".rolling"))
scaled <- quote.convert(paste0(varname,".scaled"))
#Perform the relevant tasks, using eval()
#around every variable columnname I may want
new.table[,eval(anntot):=
the.table[,rep(eval(varname),each=12)]]
new.table[,eval(monthly):=
the.table[,rep(eval(varname)/12,each=12)]]
new.table[,eval(rolling):=
rollapply(eval(monthly),mean,width=12,
fill=c(head(eval(monthly),1),
tail(eval(monthly),1)))]
new.table[,eval(scaled):=
eval(anntot)/sum(eval(rolling))*eval(rolling),
by=year]
}
Конечно, конкретный эффект на данные и переменные здесь не имеет значения, поэтому, пожалуйста, не сосредотачивайтесь на нем или не предлагайте улучшения для достижения того, что он выполняет в этом конкретном случае. То, что я ищу, скорее, является общей стратегией для рабочего процесса многократного применения произвольно сложной процедуры действий data.table
к списку столбцов или списку списков столбцов, указанным в переменной или переданным в качестве аргумента к функции, где процедура должна ссылаться программно на столбцы, названные в переменной/аргументе, и, возможно, включает в себя обновления, объединения, группировки, вызовы data.table
специальных объектов .I
, .SD
и т.д.; НО один, который проще, элегантнее, короче или проще в проектировании или внедрении или понимании, чем тот, который выше или другие, которые требуют частых quote
-ing и eval
-ing.
В частности, обратите внимание, что поскольку процедуры могут быть довольно сложными и требуют многократного обновления data.table
, а затем ссылки на обновленные столбцы, стандартный подход lapply(.SD,...), ... .SDcols = ...
обычно не является заменяемым. Кроме того, замена каждого вызова eval(a.column.name)
на DT[[a.column.name]]
не упрощает и вообще не работает вообще, так как, насколько мне известно, не работает хорошо с другими операциями data.table
.