由於data.frame
已經是一個列表,你知道,每個列表元素是相同的長度(X),速度最快的東西很可能是剛剛更新class
和row.names
屬性:
set.seed(21)
n <- 1e6
x <- list(x=rnorm(n), y=rnorm(n), z=rnorm(n))
x <- c(x,x,x,x,x,x)
system.time(a <- as.data.frame(x))
system.time(b <- do.call(data.frame,x))
system.time({
d <- x # Skip 'c' so Joris doesn't down-vote me! ;-)
class(d) <- "data.frame"
rownames(d) <- 1:n
names(d) <- make.unique(names(d))
})
identical(a, b) # TRUE
identical(b, d) # TRUE
更新 - 這是2倍〜比創建d
快:
system.time({
e <- x
attr(e, "row.names") <- c(NA_integer_,n)
attr(e, "class") <- "data.frame"
attr(e, "names") <- make.names(names(e), unique=TRUE)
})
identical(d, e) # TRUE
更新2 - 我的有關內存消耗。最近的更新使e
的兩個副本。使用attributes
函數將其減少爲只有一個副本。
set.seed(21)
f <- list(x=rnorm(n), y=rnorm(n), z=rnorm(n))
f <- c(f,f,f,f,f,f)
tracemem(f)
system.time({ # makes 2 copies
attr(f, "row.names") <- c(NA_integer_,n)
attr(f, "class") <- "data.frame"
attr(f, "names") <- make.names(names(f), unique=TRUE)
})
set.seed(21)
g <- list(x=rnorm(n), y=rnorm(n), z=rnorm(n))
g <- c(g,g,g,g,g,g)
tracemem(g)
system.time({ # only makes 1 copy
attributes(g) <- list(row.names=c(NA_integer_,n),
class="data.frame", names=make.names(names(g), unique=TRUE))
})
identical(f,g) # TRUE
休假 「可能」 出答案這是正確的。如果你使用這些調用來創建一個函數,並用長度命令替換知道n的作弊,那也是正確的。刪除所有廣泛的檢查後,您的新函數大致等同於data.frame()。所以,如果你確實知道你把這個電話轉換成正確的輸入,那麼只需按照Josh的建議來加快速度。如果你不確定,那麼data.frame是更安全的,並且do.call(data.frame,x))是下一個最快(奇怪的是)。 – John 2011-05-09 22:18:25
請看'plyr :: quickdf'確切的這個功能。 – hadley 2011-05-09 23:25:56
@hadley:'plyr :: quickdf'不提供這個功能;即它不會生成唯一的列名稱。 'plyr ::: make_names'只替換缺失的名字,沒有像'base :: make.names'這樣的'unique ='arg。 – 2011-05-10 00:58:30