r data.table lapply или для l oop для создания переменных или генерации столбцов - PullRequest
1 голос
/ 30 января 2020

Я хочу создать несколько переменных, используя формулу с R data.table. У меня есть список переменных, и для каждой из них я хочу выполнить вычисление и создать новую переменную, вставив одну и ту же строку в каждое имя столбца. Я могу заставить его работать для одной переменной за раз, но он не работает для лапы или al oop. Я подозреваю, что я что-то упускаю с R data.table и кавычки или имена переменных против строк. Нужно ли использовать ".." или переносить с помощью eval ()? Решение dplyr (или любого другого направления) также решило бы проблему.

Вот пример кода с mtcars:

library(data.table)
mtcars.dt <- setDT(mtcars)
myVars <- c("mpg", "hp", "qsec")

# Doesn't work:
for( myVar in myVars){
  mtcars.dt[, paste0(myVar, ".disp.ratio") := myVar / disp]
}

# Doesn't work:
lapply(myVars, function(myVar) mtcars.dt[, paste0(myVar, ".disp.ratio") := myVar / disp])

# Works:
mtcars.dt[, mpg.disp.ratio := mpg / disp]

# Doesn't work
for (myVar in myVars){
  mtcars.dt[, paste0(myVar, ".disp.lm.adj") := 
              myVar - 
              lm(data = .SD, formula = myVar ~ disp)$coefficients[2] * (disp - mean(disp))]
}

# Doesn't work
lapply(myVars, function(x) mtcars.dt[, paste0(x, ".disp.lm.adj") := 
                                       x - 
                                       lm(data = .SD, formula = x ~ disp)$coefficients[2] * (disp - mean(disp))])

# Works
mtcars.dt[, mpg.disp.lm.adj := 
            mpg - 
            lm(data = .SD, formula = mpg ~ disp)$coefficients[2] * (disp - mean(disp))]

Для вычисления отношения я получаю следующую ошибку:

Error in myVar/disp : non-numeric argument to binary operator 

Для регулировки лм я получаю следующую ошибку:

Error in model.frame.default(formula = myVar ~ disp, data = .SD, drop.unused.levels = TRUE) : 
  variable lengths differ (found for 'disp')

1 Ответ

1 голос
/ 30 января 2020

Мы можем использовать get

library(data.table)
for( myVar in myVars){
   mtcars.dt[, paste0(myVar, ".disp.ratio") := get(myVar) / disp]
  }

Или обернуть eval после преобразования в symbol

for( myVar in myVars){
   mtcars.dt[, paste0(myVar, ".disp.ratio") := eval(as.name(myVar)) / disp]
  }

Или другой вариант указать в .SDcols, l oop над .SD (Подмножество Data.table, выполните преобразование и создайте новые переменные с помощью присваивания (:=)

mtcars.dt[, paste0(myVars, ".disp.ratio") := lapply(.SD, `/`, disp), 
             .SDcols = myVars]

Для второго случая , мы можем создать формулу с paste

for (myVar in myVars) {
  mtcars.dt[, paste0(myVar, ".disp.lm.adj") := 
              get(myVar) - 
              lm(data = .SD, formula = paste(myVar,  "~ disp"))$coefficients[2] *
               (disp - mean(disp))]
}
...