Jeśli chcesz zadeklarować taką data.frameliczbę kolumn, prawdopodobnie trudno będzie ręcznie wpisać wszystkie klasy kolumn. Zwłaszcza jeśli możesz skorzystać z reptej metody, jest to łatwe i szybkie (około 15% szybsze niż inne rozwiązanie, które można uogólnić w ten sposób):
Jeśli żądane klasy kolumn są w wektorze colClasses, możesz wykonać następujące czynności:
library(data.table)
setnames(setDF(lapply(colClasses, function(x) eval(call(x)))), col.names)
lapplyspowoduje utworzenie listy pożądanej długości, której każdy element jest po prostu pustym wektorem wektorowym, takim jak numeric()lub integer().
setDFkonwertuje to listprzez odniesienie do data.frame.
setnames dodaje żądane nazwy przez odniesienie.
Porównanie prędkości:
classes <- c("character", "numeric", "factor",
"integer", "logical","raw", "complex")
NN <- 300
colClasses <- sample(classes, NN, replace = TRUE)
col.names <- paste0("V", 1:NN)
setDF(lapply(colClasses, function(x) eval(call(x))))
library(microbenchmark)
microbenchmark(times = 1000,
read = read.table(text = "", colClasses = colClasses,
col.names = col.names),
DT = setnames(setDF(lapply(colClasses, function(x)
eval(call(x)))), col.names))
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# read 2.598226 2.707445 3.247340 2.747835 2.800134 22.46545 1000 b
# DT 2.257448 2.357754 2.895453 2.401408 2.453778 17.20883 1000 a
Jest także szybszy niż używanie structurew podobny sposób:
microbenchmark(times = 1000,
DT = setnames(setDF(lapply(colClasses, function(x)
eval(call(x)))), col.names),
struct = eval(parse(text=paste0(
"structure(list(",
paste(paste0(col.names, "=",
colClasses, "()"), collapse = ","),
"), class = \"data.frame\")"))))
#Unit: milliseconds
# expr min lq mean median uq max neval cld
# DT 2.068121 2.167180 2.821868 2.211214 2.268569 143.70901 1000 a
# struct 2.613944 2.723053 3.177748 2.767746 2.831422 21.44862 1000 b