Подтвердить что ты не робот

Data.table: Правильный способ создания условной переменной, когда имена столбцов неизвестны?

Мой вопрос связан с созданием переменной, которая зависит от других столбцов в таблице данных. Если ни одно из имен переменных не известно заранее.

Ниже приведен пример игрушки, где у меня есть 5 строк, а новая переменная должна быть 1, когда условие равно A и 4.

library(data.table)
DT <- data.table(Con = c("A","A","B","A","B"),
                 Eval_A = rep(1,5),
                 Eval_B = rep(4,5))
Col1 <- "Con"
Col2 <- "Eval_A"
Col3 <- "Eval_B"
Col4 <- "Ans"

Код ниже работает, но кажется, что я неправильно использую пакет!

DT[,Col4:=ifelse(DT[[Col1]]=="A",
                 DT[[Col2]],
                 DT[[Col3]]),with=FALSE]

Update: Спасибо, я немного ускорил ответы ниже. Однажды на data.table с 5 миллионами строк и только соответствующие столбцы и снова после добавления 10 не соответствующих столбцов ниже приведены результаты:

+-------------------------+---------------------+------------------+
|         Method          | Only relevant cols. | With extra cols. |
+-------------------------+---------------------+------------------+
| List method             | 1.8                 | 1.91             |
| Grothendieck - get/if   | 26.79               | 30.04            |
| Grothendieck - get/join | 0.48                | 1.56             |
| Grothendieck - .SDCols  | 0.38                | 0.79             |
| agstudy - Substitute    | 2.03                | 1.9              |
+-------------------------+---------------------+------------------+

Похоже, что .SDCols лучше всего подходит для скорости и использует замену для легко читаемого кода.

4b9b3361

Ответ 1

1. получить/если Попробуйте использовать get:

DT[, (Col4) := if (get(Col1) == "A") get(Col2) else get(Col3), by = 1:nrow(DT)]

2. Получить/присоединиться или попробуйте этот подход:

setkeyv(DT, Col1)
DT[, (Col4):=get(Col3)]["A", (Col4):=get(Col2)]

3..SDCols или это:

setkeyv(DT, Col1)
DT[, (Col4):=.SD, .SDcols = Col3]["A", (Col4):=.SD, .SDcols = Col2]

UPDATE: добавлены дополнительные подходы.

Ответ 2

Используя ifelse и get:

DT[, (Col4) := ifelse (get(Col1) == "A",get(Col2) , get(Col3))]

Или используя substitute, чтобы создать выражение следующим образом:

expr <- substitute(a4 := ifelse (a1 == "A",a2 , a3),
                   list(a1=as.name(Col1),
                        a2=as.name(Col2),
                        a3=as.name(Col3),
                        a4=as.name(Col4)))

DT[, eval(expr)]