web-dev-qa-db-fra.com

Comment faire fondre et diffuser des trames de données à l'aide de dplyr?

Récemment, je fais toutes mes manipulations de données en utilisant dplyr et c'est un excellent outil pour cela. Cependant, je ne parviens pas à faire fondre ou à caster une trame de données à l'aide de dplyr. Y'a-t'il un quelconque moyen d'y arriver? En ce moment, j'utilise reshape2 à cet effet.

Je veux une solution 'dplyr' pour:

require(reshape2)
data(iris)
dat <- melt(iris,id.vars="Species")
40
Koundy

Le successeur de reshape2 Est tidyr. Les équivalents de melt() et dcast() sont gather() et spread() respectivement. L'équivalent de votre code serait alors

library(tidyr)
data(iris)
dat <- gather(iris, variable, value, -Species)

Si vous avez importé magrittr, vous pouvez utiliser l'opérateur pipe comme dans dplyr, c'est-à-dire écrire

dat <- iris %>% gather(variable, value, -Species)

Notez que vous devez spécifier explicitement les noms de variable et de valeur, contrairement à melt(). Je trouve la syntaxe de gather() assez pratique, car vous pouvez simplement spécifier les colonnes que vous souhaitez convertir en format long, ou spécifier celles que vous souhaitez conserver dans le nouveau bloc de données en les préfixant avec '- '(comme pour les espèces ci-dessus), qui est un peu plus rapide à taper que dans melt(). Cependant, j'ai remarqué que sur ma machine au moins, tidyr peut être sensiblement plus lent que reshape2.

Modifier En réponse au commentaire de @hadley ci-dessous, je publie des informations de synchronisation comparant les deux fonctions sur mon PC.

library(microbenchmark)
microbenchmark(
    melt = melt(iris,id.vars="Species"), 
    gather = gather(iris, variable, value, -Species)
)
# Unit: microseconds
#    expr     min       lq  median       uq      max neval
#    melt 278.829 290.7420 295.797 320.5730  389.626   100
#  gather 536.974 552.2515 567.395 683.2515 1488.229   100

set.seed(1)
iris1 <- iris[sample(1:nrow(iris), 1e6, replace = T), ] 
system.time(melt(iris1,id.vars="Species"))
#    user  system elapsed 
#   0.012   0.024   0.036 
system.time(gather(iris1, variable, value, -Species))
#    user  system elapsed 
#   0.364   0.024   0.387 

sessionInfo()
# R version 3.1.1 (2014-07-10)
# Platform: x86_64-pc-linux-gnu (64-bit)
# 
# locale:
#  [1] LC_CTYPE=en_GB.UTF-8       LC_NUMERIC=C              
#  [3] LC_TIME=en_GB.UTF-8        LC_COLLATE=en_GB.UTF-8    
#  [5] LC_MONETARY=en_GB.UTF-8    LC_MESSAGES=en_GB.UTF-8   
#  [7] LC_PAPER=en_GB.UTF-8       LC_NAME=C                 
#  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
# [11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C       

# attached base packages:
# [1] stats     graphics  grDevices utils     datasets  methods   base     
# 
# other attached packages:
# [1] reshape2_1.4         microbenchmark_1.3-0 magrittr_1.0.1      
# [4] tidyr_0.1           
# 
# loaded via a namespace (and not attached):
# [1] assertthat_0.1 dplyr_0.2      parallel_3.1.1 plyr_1.8.1     Rcpp_0.11.2   
# [6] stringr_0.6.2  tools_3.1.1   
66
konvas

De plus, le cast peut utiliser tidyr::spread()

Exemple pour vous

library(reshape2)
library(tidyr)
library(dplyr)

# example data : `mini_iris`
(mini_iris <- iris[c(1, 51, 101), ])

# melt
(melted1 <- mini_iris %>% melt(id.vars = "Species"))         # on reshape2
(melted2 <- mini_iris %>% gather(variable, value, -Species)) # on tidyr

# cast
melted1 %>% dcast(Species ~ variable, value.var = "value") # on reshape2
melted2 %>% spread(variable, value)                        # on tidyr
5
Lovetoken

Pour ajouter aux réponses ci-dessus en utilisant @ Lovetoken's mini_iris exemple (c'est trop complexe pour un commentaire) - pour les nouveaux venus qui ne comprennent pas ce que l'on entend par fusion et coulée.

library(reshape2)
library(tidyr)
library(dplyr)

# example data : `mini_iris`
mini_iris <- iris[c(1, 51, 101), ]

# mini_iris
#Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
#1            5.1         3.5          1.4         0.2     setosa
#51           7.0         3.2          4.7         1.4 versicolor
#101          6.3         3.3          6.0         2.5  virginica

Melt prend la trame de données et se développe dans une longue liste de valeurs. Pas efficace mais peut être utile si vous devez combiner des ensembles de données. Pensez à la structure d'un glaçon fondant sur une table et s'étalant.

melted1 <- testiris %>% melt(id.vars = "Species")

> nrow(melted1)
[1] 12

head(melted1)
# Species     variable      value
# 1     setosa Sepal.Length   5.1
# 2 versicolor Sepal.Length   7.0
# 3  virginica Sepal.Length   6.3
# 4     setosa  Sepal.Width   3.5
# 5 versicolor  Sepal.Width   3.2
# 6  virginica  Sepal.Width   3.3

Vous pouvez voir comment les données ont été divisées en plusieurs lignes de valeur. Les noms des colonnes sont désormais du texte dans une colonne variable.

le casting se réassemblera à un data.table ou data.frame.

2
micstr