#r #data.table
#r #data.table
Вопрос:
У меня есть большой список имен столбцов (переменных) R data.table, и я хочу создать столбец, содержащий произведение этих столбцов.
Пример:
col_names <- c("season_1","season_2","season_3")
DT_example <- data.table(id=1:4,
season_1=c(1,1,0,0),
season_2=c(0,1,1,1),
season_3=c(1,0,1,0),
product=1)
data.table:
id season_1 season_2 season_3 product
1: 1 1 0 1 1
2: 2 1 1 1 1
3: 3 0 1 1 1
4: 4 0 1 0 1
Решение, которое у меня есть, использует цикл «for», но это не очень эффективно:
for(inc in col_names){
nm1 <- as.symbol(inc)
DT_example[,product:= product * eval(nm1)]
}
Результат:
id season_1 season_2 season_3 product
1: 1 1 0 1 0
2: 2 1 1 0 0
3: 3 1 1 1 1
4: 4 0 1 0 0
Есть ли более быстрый способ сделать это, используя собственный синтаксис data.table?
Комментарии:
1.
DT_example[, product := Reduce("*", .SD), .SDcols = col_names]
2. Показанные в примере данные и код для их воспроизведения не совпадают.
Ответ №1:
Вот четыре варианта. Первый, безусловно, самый эффективный, но предполагает, что мы имеем дело только с нулями и единицами.
DT_example[, product := do.call(pmin, .SD), .SDcols = patterns("season")]
DT_example[, product := Reduce(`*`, .SD), .SDcols = patterns("season")]
DT_example[, product := apply(.SD, 1, prod), .SDcols = patterns("season")]
DT_example[, product := melt(.SD, id.vars = "id")[, prod(value), by = id]$V1]
# > DT_example
# id season_1 season_2 season_3 product
# 1: 1 1 0 1 0
# 2: 2 1 1 1 1
# 3: 3 0 1 1 0
# 4: 4 0 1 0 0
Данные:
DT_example <- data.table(
id=1:4,
season_1=c(1,1,0,0),
season_2=c(0,1,1,1),
season_3=c(1,1,1,0),
product=1
)
Ответ №2:
Я думаю, вы могли бы использовать функции «применить» и «prod»:
DT_example$product = apply(DT_example[,2:4], 1, prod)
Это применение функции «prod» (умножает каждый элемент того, что получает ir), к каждой строке (определяемой аргументом «1», поскольку «2» будет столбцом) «DT_example [,2: 4]».
Ответ №3:
Мы можем использовать prod
сгруппированные по последовательности строк после выбора столбцов .SDcols
. При prod
na.rm
необходимости также есть возможность удалить NA
элементы.
DT_example[, Product := prod(.SD, na.rm = TRUE), by = 1:nrow(DT_example),
.SDcols = patterns("season")]
-вывод
DT_example
# id season_1 season_2 season_3 product Product
#1: 1 1 0 1 1 0
#2: 2 1 1 1 1 1
#3: 3 0 1 1 1 0
#4: 4 0 1 0 1 0