2014-07-22 2 views
24

Kürzlich mache ich alle meine Datenmanipulationen mit dplyr und es ist ein ausgezeichnetes Werkzeug dafür. Ich bin jedoch nicht in der Lage, einen Datenrahmen mit dplyr zu schmelzen oder zu werfen. Gibt es eine Möglichkeit, das zu tun? Im Moment verwende ich reshape2 für diesen Zweck.Wie schmelzen und casten Sie Datenrahmen mit dplyr?

Ich will 'dplyr' Lösung für:

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

Der Nachfolger von 'reshape2' ist' tidyr'. Das Äquivalent von "schmelzen" und "übertragen" ist jeweils "sammeln" und "ausbreiten". Es ist noch nicht auf CRAN verfügbar, aber Sie können es von Github (https://github.com/hadley/tidyr) herunterladen! – konvas

+3

@konvas Update: 'tidyr' ist jetzt auf CRAN (http://cran.r-project.org/web/packages/tidyr/index.html) – dickoa

+0

@konvas warum nennst du es nicht einfach als richtige Antwort? – Beasterfield

Antwort

50

Der Nachfolger reshape2 ist tidyr. Das Äquivalent von melt() und dcast() sind gather() bzw. spread(). Das entspricht der Code würde dann

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

sein Wenn Sie magrittr importiert Sie die Pipe Operator wie in dplyr verwenden können, das heißt

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

Hinweis schreiben, dass Sie die Variable und Wertnamen angeben müssen explizit, anders als in melt(). Ich finde die Syntax von gather() sehr praktisch, weil Sie einfach die Spalten angeben können, die in das lange Format konvertiert werden sollen, oder die, die im neuen Datenrahmen bleiben sollen, indem Sie ihnen ein '-' voranstellen (genau wie bei Species) oben), die ein bisschen schneller zu tippen ist als in melt(). Allerdings habe ich festgestellt, dass auf meiner Maschine tidyr deutlich langsamer als reshape2 sein kann.

Bearbeiten Als Antwort auf den Kommentar von @hadley unten, posten ich einige Timing-Informationen, die die beiden Funktionen auf meinem PC vergleichen.

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 
+0

Es sollte nicht merklich langsamer sein, da es im Grunde alle den gleichen Code ist. Wenn Sie ein reproduzierbares Beispiel liefern können, würde ich es gerne sehen. – hadley

+0

@hadley Ich habe ein paar Informationen gepostet. Ich weiß, dass dies wahrscheinlich nicht auf den Code zurückzuführen ist und möglicherweise spezifisch für mein System ist. Der 'Benutzer' Teil von 'system.time()' scheint zu sein, was den Unterschied macht, obwohl ich nicht genau weiß, was das bedeutet, aber ich bin sicher, du wirst es wissen :) – konvas

+0

@hadley Für mich auch schmelzen führt schneller als zu sammeln --- wird für eine Weile daran festhalten. – apc

3

Zusätzlich kann Guss tidyr::spread()

Beispiel für die Verwendung werden für Sie

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 
1

zu Antworten mini_iris Beispiel oben mit @ Lovetoken ist hinzuzufügen (dies für einen Kommentar zu komplex ist) - für jene Neulinge, die nicht verstehen, was mit Schmelze und Gießen gemeint ist.

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 

Schmelze nimmt den Datenrahmen und expandiert in eine lange Liste von Werten. Nicht effizient, kann aber nützlich sein, wenn Sie Datensätze kombinieren müssen. Denken Sie an die Struktur eines Eiswürfels, das auf einer Tischplatte schmilzt und sich ausbreitet.

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 

können Sie sehen, wie die Daten nun in viele Zeilen Wert gebrochen. Die Spaltennamen sind jetzt Text in einer Variablenspalte.

casting wird wieder zu einer data.table oder data.frame zusammengebaut.

Verwandte Themen