Je fais un projet scolaire de nettoyage de données avec le package tidyverse . Maintenant, j'obtiens une sortie de liste de purrr :: map () comme ceci:
df <- data.frame(Value = reduce(mylist, c))
df$Class <- rep(names(mylist), sapply(mylist, length))
df
Value Class
1 1970-06-12 A
2 1984-05-28 A
3 1967-06-28 A
4 1982-12-14 A
5 1966-02-04 B
6 1967-02-21 B
7 1977-07-19 C
8 1968-03-11 C
9 1964-02-13 C
Je veux les empiler dans:
(mylist <- list(A = as.Date(sample(1e3:1e4, 4), origin = "1960-01-01"),
B = as.Date(sample(1e3:1e4, 2), origin = "1960-01-01"),
C = as.Date(sample(1e3:1e4, 3), origin = "1960-01-01")))
$A
[1] "1970-06-12" "1984-05-28" "1967-06-28" "1982-12-14"
$B
[1] "1966-02-04" "1967-02-21"
$C
[1] "1977-07-19" "1968-03-11" "1964-02-13"
Date . stack (myylist) ne fonctionne pas dans la liste de dates. Existe-t-il des méthodes pour y parvenir efficacement avec des fonctions de tidyverse ou d'autres packages?
3 Réponses :
Nous pouvons utiliser stack
system.time({rbindlist(lapply(mylist2, as.data.table), idcol = names(mylist2))})
# user system elapsed
# 2.889 0.160 3.029
system.time({enframe(mylist2) %>%
unnest})
# user system elapsed
# 0.149 0.004 0.152
system.time({data.frame(value = reduce(mylist2, c),
class = rep(names(mylist2), lengths(mylist2)))})
# user system elapsed
# 14.714 8.890 23.550
library(microbenchmark)
microbenchmark(
ak1 = reshape2::melt(mylist2),
ak2 = enframe(mylist2) %>%
unnest,
st1 = data.table::melt(mylist2),
st2 = rbindlist(lapply(mylist2, as.data.table), idcol = names(mylist2)),
unit = 'relative', times = 10L)
#Unit: relative
# expr min lq mean median uq max neval cld
# ak1 26.51333 24.38488 21.52345 23.65577 19.36023 18.71291 10 c
# ak2 1.00000 1.00000 1.00000 1.00000 1.00000 1.00000 10 a
# st1 25.34465 24.56934 21.97353 26.27053 19.23078 17.32802 10 c
# st2 16.19268 16.96023 14.28353 16.25288 12.69549 11.58340 10 b
Pour la question mise à jour, soit melt de reshape2 ou data.table peut être utilisé
mylist2 <- rep(mylist, 1e4) #slightly bigger list
system.time({data.table::melt(mylist2)}) #Sotos solution
#user system elapsed
# 3.432 0.025 3.436
system.time({reshape2::melt(mylist2)})
#user system elapsed
# 3.461 0.021 3.472
Ou en utilisant tidyverse p>
library(tidyverse)
enframe(mylist) %>%
unnest
# A tibble: 9 x 2
# name value
# <chr> <date>
#1 A 3658-09-23
#2 A 2390-06-01
#3 A 2744-01-09
#4 A 2432-02-21
#5 B 4077-11-13
#6 B 4022-11-13
#7 C 3923-11-19
#8 C 2836-08-20
#9 C 3411-01-23
Voici quelques benchmarks utilisant les quatre solutions postées
library(reshape2) melt(mylist) # value L1 #1 3658-09-23 A #2 2390-06-01 A #3 2744-01-09 A #4 2432-02-21 A #5 4077-11-13 B #6 4022-11-13 B #7 3923-11-19 C #8 2836-08-20 C #9 3411-01-23 C
Le melt Les fonctions des deux packages n'ont qu'une légère différence de performances
stack(mylist) # values ind #1 1 A #2 2 A #3 3 A #4 4 B #5 5 B #6 6 B #7 7 B #8 8 C #9 9 C
Je modifie ma question. stack () ne fonctionne pas dans la liste de dates.
Désolé, au début, je pense que la solution d'une liste numérique équivaut à une liste de dates. Merci pour votre modification.
@DarrenTsai Je pense que les attributs de Date ont créé un problème dans stack . J'ai mis à jour avec une autre solution
ajouté cela dans la liste
Nous pouvons utiliser le package data.table qui est très efficace,
data.table::melt(mylist)
De plus, data.table :: melt () fera également le travail (similaire à la solution reshape2 de @ akrun), c'est-à-dire
library(data.table) rbindlist(lapply(mylist, as.data.table), idcol = names(mylist)) # A V1 #1: A 4394-02-08 #2: A 4580-05-16 #3: A 2476-01-24 #4: A 2928-11-03 #5: B 4652-12-02 #6: B 3758-02-20 #7: C 2331-09-07 #8: C 3092-02-15 #9: C 3494-03-07
Nous avons déjà les solutions data.table et tidyverse (qui sont très efficaces) mais juste pour être complet, voici une approche de base R
data.frame(value = do.call(c, mylist), class = rep(names(mylist), lengths(mylist)))
Je modifie ma question.
stack ()ne fonctionne pas dans la liste de dates.