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")
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
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
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.