A data.table
ответ для вашего рассмотрения. Мы просто используем setattr()
из него, который работает на data.frame
, и столбцы data.frame
. Нет необходимости конвертировать в data.table
.
Данные испытаний снова:
dat <- cbind(rep(1:5,50000),rep(5:1,50000),rep(c(1L,2L,4L,5L,3L),50000))
dat <- cbind(dat,dat,dat,dat,dat,dat,dat,dat,dat,dat,dat,dat)
dat <- as.data.frame(dat)
re.codes <- c("This","That","And","The","Other")
Теперь измените класс и установите уровни каждого столбца напрямую, по ссылке:
require(data.table)
system.time(for (i in 1:ncol(dat)) {
setattr(dat[[i]],"levels",re.codes)
setattr(dat[[i]],"class","factor")
}
# user system elapsed
# 0 0 0
identical(dat, <result in question>)
# [1] TRUE
0,00 ли победит? При увеличении размера данных этот метод остается на уровне 0,00 .
Хорошо, я признаю, я немного изменил входные данные, чтобы они были integer
для всех столбцов (вопрос содержит double
входных данных в трети столбцов). Эти столбцы double
необходимо преобразовать в integer
, поскольку factor
действителен только для integer
векторов. Как уже упоминалось в других ответах.
Таким образом, строго с входными данными в вопросе, включая преобразование double
в integer
:
dat <- cbind(rep(1:5,50000),rep(5:1,50000),rep(c(1,2,4,5,3),50000))
dat <- cbind(dat,dat,dat,dat,dat,dat,dat,dat,dat,dat,dat,dat)
dat <- as.data.frame(dat)
re.codes <- c("This","That","And","The","Other")
system.time(for (i in 1:ncol(dat)) {
if (!is.integer(dat[[i]]))
set(dat,j=i,value=as.integer(dat[[i]]))
setattr(dat[[i]],"levels",re.codes)
setattr(dat[[i]],"class","factor")
})
# user system elapsed
# 0.06 0.01 0.08 # on my slow netbook
identical(dat, <result in question>)
# [1] TRUE
Обратите внимание, что set
также работает на data.frame
. Вам не нужно конвертировать в data.table
, чтобы использовать его.
Это очень маленькие времена, ясно. Поскольку это только небольшой входной набор данных:
dim(dat)
# [1] 250000 36
object.size(dat)
# 68.7 Mb
Увеличение от этого должно выявить большие различия. Но даже в этом случае я думаю, что это должно быть (примерно) как можно быстрее. Впрочем, при таком размере не имеет значения, о чем кто-либо думает.
Функция setattr
также входит в пакет bit
, кстати. Таким образом, метод 0.00 можно выполнить с помощью data.table
или bit
. Чтобы выполнить преобразование типа по ссылке (если требуется), необходимо либо set
или :=
(оба в data.table
), afaik.