2015-11-18 3 views
14

Ich habe einen großen Datensatz, der split() in R drosselt. Ich kann dplyr group_by verwenden (was sowieso eine bevorzugte Methode ist), aber ich kann nicht bestehen Ergebnis grouped_df als eine Liste von Datenrahmen, ein Format, das von meinen aufeinanderfolgenden Verarbeitungsschritten erforderlich ist (ich muss auf SpatialDataFrames und ähnliche zwingen).Emulate split() mit dplyr group_by: gebe eine Liste von Datenframes zurück

betrachten ein Beispieldatensatz:

df = as.data.frame(cbind(c("a","a","b","b","c"),c(1,2,3,4,5), c(2,3,4,2,2))) 
listDf = split(df,df$V1) 

kehrt

$a 
    V1 V2 V3 
1 a 1 2 
2 a 2 3 

$b 
    V1 V2 V3 
3 b 3 4 
4 b 4 2 

$c 
    V1 V2 V3 
5 c 5 2 

ich dies mit group_by (wie group_by(df,V1) etwas) emulieren möchte aber wieder ein, grouped_df. Ich weiß, dass do der Lage sein sollte, mir zu helfen, aber ich bin nicht sicher, über die Nutzung (auch link für eine Diskussion sehen.)

Beachten Sie, dass durch den Namen des Faktors Namen jeder Liste verteilen, die verwendet wurde, um diese Gruppe zu etablieren - Dies ist eine gewünschte Funktion (letztlich, Bonus-Kudos für eine Möglichkeit, diese Namen aus der Liste der DFS zu extrahieren).

+4

Warum ist 'group_by' über' split' bevorzugt? Weil es von Hadley geschrieben wurde? 'group_by' hat seinen Platz und es ist nicht dafür gedacht, einen Datensatz in verschiedene Datenrahmen zu teilen, während' split' genau das erreichen soll. –

+2

Nein, nicht weil es von hadley geschrieben wurde, sondern weil es komplett ist - und zwar schnell. Ich habe einen Datensatz, der ein df von 400mb ist, und split Ergebnisse in eine Monstrosität (nicht sicher, warum es die Größe aufbläht), und stürzt R beim Speichern ab. Dies ist ein Trainingsdatensatz, der echte ist dann ein 8,5 GB-Datensatz (1 GB als RData). Gruppe funktioniert, Split ist fehlgeschlagen. Ich habe Bigsplit probiert, aber auch nicht geschafft. Immer noch zurück zur Frage - wie geht das mit group_by (und dplyr)? – MartinT

+1

Auch hier war 'group_by' nicht dafür gedacht, einen Datensatz in separate Datensätze aufzuteilen. 'do' wird wahrscheinlich viel langsamer sein als' split'. 'Split' ist vollständig vektorisiert und kompiliert und ich sehe nicht, warum es langsamer als jede andere Alternative ist. –

Antwort

12

Um ‚Stock‘ dplyr, können Sie auch verwenden können plyr statt split: wie Sie den neuen Spaltennamen

library(plyr) 

dlply(df, "V1", identity) 
#$a 
# V1 V2 V3 
#1 a 1 2 
#2 a 2 3 

#$b 
# V1 V2 V3 
#1 b 3 4 
#2 b 4 2 

#$c 
# V1 V2 V3 
#1 c 5 2 
+13

Wie 'plyr' mit' dplyr' zu kleben ist? –

+2

Vielen Dank. Das ergibt genau das, was ich wollte, und wird schnell fertig. Ich werde es nicht als die richtige Antwort bezeichnen, wie ich bin immer noch interessiert, wie das Ergebnis von group_by als Liste von Datenrahmen exportiert werden kann, aber danke - Sie haben mein Problem gelöst und ich habe etwas gelernt! Interessante Sache ist, dass von einem 380Mb Datensatz, das Ergebnis behauptet, eine 340Gb Liste zu sein! Ich hoffe, ich kann es speichern, scheint seltsam - aber es ist sehr schnell, in etwa 5 Minuten abgeschlossen. – MartinT

+0

Hatte das gleiche strukturierte Problem und konnte nicht mit 'mein.data%>% group_by (colA)%>% tun (. , function.that.returns.list) 'weil' dplyr' die Ergebnisse in einem 'dat.frame' erwartet. Die Verwendung Ihrer Methode funktionierte perfekt "Ergebnisse <- dlply (my.data," colA ", function.that.returns.list)' – davidski

6

Sie mit do so lange eine Liste von Datenrahmen von group_by erhalten können, wo die Daten Frames werden gespeichert und dann diese Spalte in lapply.

listDf = df %>% group_by(V1) %>% do(vals=data.frame(.)) %>% select(vals) %>% lapply(function(x) {(x)}) 
listDf[[1]] 
#[[1]] 
# V1 V2 V3 
#1 a 1 2 
#2 a 2 3 

#[[2]] 
# V1 V2 V3 
#1 b 3 4 
#2 b 4 2 

#[[3]] 
# V1 V2 V3 
#1 c 5 2 
+2

mit der neuesten Version von 'tidyr' (0.4.1), können Sie' do (vals = data.frame (.)) 'Durch' nest() 'ersetzen. 'vals' wird standardmäßig 'data' genannt. – aurelien

+0

Beachten Sie, dass die Verwendung von' nest() 'anstelle von' do' nicht genau dasselbe ist; die resultierenden Tabellen haben nur Spalten V2 und V3; Die Gruppierungsvariable ist verloren. – cboettig

+5

eine identische, aber etwas kürzere Version wäre: 'df%>% group_by (V1)%>% do (Daten = (.))%>% Select (Daten)%>% map (identity)' – cboettig

7

Vergleicht man die Basis, plyr und dplyr Lösungen, so scheint es nach wie vor die Basis ein viel schneller ist!

df <- data_frame(Group1=rep(LETTERS, each=1000), 
      Group2=rep(rep(1:10, each=100),26), 
      Value=rnorm(26*1000)) 

library(plyr) 
library(dlyr) 
library(dlyr) 

microbenchmark(Base=df %>% 
      split(.$Group2, .$Group1), 
      dplyr=df %>% 
      group_by(Group1, Group2) %>% 
      do(data = (.)) %>% 
      select(data) %>% 
      lapply(function(x) {(x)}) %>% .[[1]], 
      plyr=dlply(df, c("Group1", "Group2"), as.tbl), 
      times=50) 

Gibt:

Unit: milliseconds 
    expr  min  lq  mean median  uq  max neval 
    Base 1.898213 1.977818 2.056877 2.032882 2.077582 2.729119 50 
dplyr 30.967926 31.502983 33.289824 32.029863 33.135550 48.245150 50 
    plyr 47.702301 49.033336 51.915533 50.961585 54.407141 65.961197 50 
Verwandte Themen