Ответ 1
Полностью переписано 2015-11-24, чтобы исправить ошибку в предыдущих версиях.
Также добавлены более современные опции на 2019-09-27
У вас есть несколько вариантов.
Обработать все целевые столбцы с помощью встроенного вызова
lapply()
, используя:=
, чтобы назначить измененные значения на месте. Этот полагается на:=
очень удобную поддержку для одновременного назначения нескольким столбцам, указанным в его LHS.Используйте цикл
for
для запуска по целевым столбцам по одному, используяset()
для изменения значения каждого из них по очереди.Используйте цикл
for
для итерации по нескольким "наивным" вызовам на[.data.table()
, каждый из которых изменяет один столбец.
Эти методы кажутся одинаково быстрыми, поэтому какой из них вы используете в основном дело вкуса. (1) красиво компактный и выразительный. Это то, что я чаще всего использую, хотя вы можете найти (2) легче читать. Поскольку они обрабатывают и изменяют столбцы по одному, (2) или (3) будут иметь преимущество в редкой ситуации, когда ваш data.table настолько велик, что вы рискуете столкнуться с ограничениями навязанная вашей R-сессией доступная память.
library(data.table)
## Create three identical 1000000-by-20 data.tables
DT1 <- data.table(1:1e6,
as.data.table(replicate(1e6, paste(sample(letters, nr, TRUE),
sample(letters, nr, TRUE)))))
cnames <- c("ID", paste0("X", 1:19))
setnames(DT1, cnames)
DT2 <- copy(DT1); DT3 <- copy(DT1)
## Method 1
system.time({
DT1[, .SDcols=cnames[-1L], cnames[-1L] :=
lapply(.SD, function(x) gsub(" ", "_", x, fixed=TRUE)), ]
})
## user system elapsed
## 10.90 0.11 11.06
## Method 2
system.time({
for(cname in cnames[-1]) {
set(DT2, j=cname, value=gsub(" ", "_", DT2[[cname]], fixed=TRUE))
}
})
## user system elapsed
## 10.65 0.05 10.70
## Method 3
system.time({
for(cname in cnames[-1]) {
DT3[ , (cname) := gsub(" ", "_", get(cname), fixed=TRUE)]
}
})
## user system elapsed
## 10.33 0.03 10.37
Для получения более подробной информации о set()
и :=
прочитайте их страницу помощи, которую можно получить, набрав ?set
или ?":="
.