Les data.frames sont stockés sous forme de listes, je crois. La coercition semble donc la meilleure solution :
as.list(as.data.frame(x))
> as.list(as.data.frame(x))
$V1
[1] 1 2 3 4 5
$V2
[1] 6 7 8 9 10
Les résultats de l'analyse comparative sont intéressants. as.data.frame est plus rapide que data.frame, soit parce que data.frame doit créer un tout nouvel objet, soit parce que le suivi des noms de colonnes est coûteux (voir la comparaison c(unname()) vs c()) ? La solution lapply proposée par @Tommy est plus rapide d'un ordre de grandeur. Les résultats de as.data.frame() peuvent être quelque peu améliorés en les contraignant manuellement.
manual.coerce <- function(x) {
x <- as.data.frame(x)
class(x) <- "list"
x
}
library(microbenchmark)
x <- matrix(1:10,ncol=2)
microbenchmark(
tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i) ,
as.list(data.frame(x)),
as.list(as.data.frame(x)),
lapply(seq_len(ncol(x)), function(i) x[,i]),
c(unname(as.data.frame(x))),
c(data.frame(x)),
manual.coerce(x),
times=1000
)
expr min lq
1 as.list(as.data.frame(x)) 176221 183064
2 as.list(data.frame(x)) 444827 454237
3 c(data.frame(x)) 434562 443117
4 c(unname(as.data.frame(x))) 257487 266897
5 lapply(seq_len(ncol(x)), function(i) x[, i]) 28231 35929
6 manual.coerce(x) 160823 167667
7 tapply(x, rep(1:ncol(x), each = nrow(x)), function(i) i) 1020536 1036790
median uq max
1 186486 190763 2768193
2 460225 471346 2854592
3 449960 460226 2895653
4 271174 277162 2827218
5 36784 37640 1165105
6 171088 176221 457659
7 1052188 1080417 3939286
is.list(manual.coerce(x))
[1] TRUE
1 votes
Je me demande si une solution Rccp optimisée ne serait pas plus rapide.
3 votes
Avec R 3.6 publié il y a plusieurs années, cette réponse (en utilisant
asplit
) devrait être acceptée.