Wie teile ich einen Datenrahmen?

73

Ich möchte einen Datenrahmen in mehrere kleinere aufteilen. Dies scheint eine sehr triviale Frage zu sein, ich kann jedoch keine Lösung für die Websuche finden.

Leo5188
quelle
3
nie verstanden split(), aber das Verwenden ntilevondplyr und das Filtern nach dem Gruppenindex ("Quartil") hat das getan, was ich wollte : group = df[df$quartile==i,].
jozxyqk

Antworten:

60

Möglicherweise möchten Sie den Datenrahmen auch in eine beliebige Anzahl kleinerer Datenrahmen schneiden. Hier schneiden wir in zwei Datenrahmen.

x = data.frame(num = 1:26, let = letters, LET = LETTERS)
set.seed(10)
split(x, sample(rep(1:2, 13)))

gibt

$`1`
   num let LET
3    3   c   C
6    6   f   F
10  10   j   J
12  12   l   L
14  14   n   N
15  15   o   O
17  17   q   Q
18  18   r   R
20  20   t   T
21  21   u   U
22  22   v   V
23  23   w   W
26  26   z   Z

$`2`
   num let LET
1    1   a   A
2    2   b   B
4    4   d   D
5    5   e   E
7    7   g   G
8    8   h   H
9    9   i   I
11  11   k   K
13  13   m   M
16  16   p   P
19  19   s   S
24  24   x   X
25  25   y   Y

Sie können einen Datenrahmen auch basierend auf einer vorhandenen Spalte teilen. So erstellen Sie beispielsweise drei Datenrahmen basierend auf der cylSpalte in mtcars:

split(mtcars,mtcars$cyl)
Greg
quelle
1
Hey Greg, ich konnte die Syntax für den Beispielbefehl nicht verstehen, kannst du das erklären?
Anirudh
"Möglicherweise möchten Sie den Datenrahmen auch in eine beliebige Anzahl kleinerer Datenrahmen schneiden. Hier schneiden wir in zwei Datenrahmen." Wie ist dies eine beliebige Anzahl von Datenrahmen, wenn Sie hier zwei Datenrahmen angeben?
user5359531
1
@ user5359531, hier beliebig zwei Datenrahmen.
Demo
19

Wenn Sie einen Datenrahmen nach den Werten einer Variablen aufteilen möchten, würde ich die Verwendung daply()aus dem plyrPaket vorschlagen .

library(plyr)
x <- daply(df, .(splitting_variable), function(x)return(x))

Jetzt xist ein Array von Datenrahmen. Um auf einen der Datenrahmen zuzugreifen, können Sie ihn mit dem Namen der Ebene der Aufteilungsvariablen indizieren.

x$Level1
#or
x[["Level1"]]

Ich bin mir sicher, dass es keine clevereren Möglichkeiten gibt, mit Ihren Daten umzugehen, bevor Sie sie in viele Datenrahmen aufteilen.

JoFrhwld
quelle
Bitte geben Sie im Voraus das Paket an, von dem eine Nicht-Basisfunktion stammt - vermutlich meinen Sie daply von Paket plyr?
Mdsumner
Ich habe Plyr in mein Code-Snippet geladen, daher dachte ich, es sei klar, aber ich werde die Antwortprosa aus Gründen der Klarheit bearbeiten.
JoFrhwld
Ich schlug dlplyzuerst vor, aber es benannte die Einträge nicht automatisch nach der Gruppierungsvariablen. Ich weiß nicht, was ich zuerst getan habe, aber offensichtlich daplyfunktioniert es nur, wenn eine Funktion angegeben ist. Ich habe die Antwort bearbeitet, um zu arbeiten.
JoFrhwld
13

Ich habe gerade eine Art RFC gepostet, die Ihnen helfen könnte: Teilen Sie einen Vektor in Blöcke in R.

x = data.frame(num = 1:26, let = letters, LET = LETTERS)
## number of chunks
n <- 2
dfchunk <- split(x, factor(sort(rank(row.names(x))%%n)))
dfchunk
$`0`
   num let LET
1    1   a   A
2    2   b   B
3    3   c   C
4    4   d   D
5    5   e   E
6    6   f   F
7    7   g   G
8    8   h   H
9    9   i   I
10  10   j   J
11  11   k   K
12  12   l   L
13  13   m   M

$`1`
   num let LET
14  14   n   N
15  15   o   O
16  16   p   P
17  17   q   Q
18  18   r   R
19  19   s   S
20  20   t   T
21  21   u   U
22  22   v   V
23  23   w   W
24  24   x   X
25  25   y   Y
26  26   z   Z

Prost, Sebastian

Sebastian
quelle
13

Sie könnten auch verwenden

data2 <- data[data$sum_points == 2500, ]

Dadurch wird ein Datenrahmen mit den Werten erstellt, bei denen sum_points = 2500 ist

Es gibt :

airfoils sum_points field_points   init_t contour_t   field_t
...
491        5       2500         5625 0.000086  0.004272  6.321774
498        5       2500         5625 0.000087  0.004507  6.325083
504        5       2500         5625 0.000088  0.004370  6.336034
603        5        250        10000 0.000072  0.000525  1.111278
577        5        250        10000 0.000104  0.000559  1.111431
587        5        250        10000 0.000072  0.000528  1.111524
606        5        250        10000 0.000079  0.000538  1.111685
....
> data2 <- data[data$sum_points == 2500, ]
> data2
airfoils sum_points field_points   init_t contour_t   field_t
108        5       2500          625 0.000082  0.004329  0.733109
106        5       2500          625 0.000102  0.004564  0.733243
117        5       2500          625 0.000087  0.004321  0.733274
112        5       2500          625 0.000081  0.004428  0.733587
Dimitar Slavchev
quelle
Hallo, wie würden Sie vorgehen, wenn Sie es dynamisch in einen anderen Datenrahmen aufteilen möchten, basierend auf eindeutigen Werten in dieser Spalte.
KRazzy R
5

Die gewünschte Antwort hängt stark davon ab, wie und warum Sie den Datenrahmen aufteilen möchten.

Wenn Sie beispielsweise einige Variablen weglassen möchten, können Sie neue Datenrahmen aus bestimmten Spalten der Datenbank erstellen. Die Indizes in Klammern nach dem Datenrahmen beziehen sich auf Zeilen- und Spaltennummern. Eine vollständige Beschreibung finden Sie unter Spoetry.

newdf <- mydf[,1:3]

Oder Sie können bestimmte Zeilen auswählen.

newdf <- mydf[1:3,]

Diese Indizes können auch logische Tests sein, z. B. die Auswahl von Zeilen, die einen bestimmten Wert enthalten, oder von Faktoren mit einem gewünschten Wert.

Was willst du mit den übrig gebliebenen Brocken machen? Müssen Sie für jeden Teil der Datenbank dieselbe Operation ausführen? Dann möchten Sie sicherstellen, dass die Teilmengen des Datenrahmens in einem praktischen Objekt wie einer Liste enden, mit dessen Hilfe Sie für jeden Teil des Datenrahmens denselben Befehl ausführen können.

Ben M.
quelle
3

Wenn Sie in einer der Spalten nach Werten aufteilen möchten, können Sie verwenden lapply. Zum Beispiel, um ChickWeightfür jedes Küken in einen separaten Datensatz aufzuteilen :

data(ChickWeight)
lapply(unique(ChickWeight$Chick), function(x) ChickWeight[ChickWeight$Chick == x,])
Mikeck
quelle
3

Das Aufteilen des Datenrahmens erscheint kontraproduktiv. Verwenden Sie stattdessen das Split-Apply-Combine-Paradigma, z. B. generieren Sie einige Daten

df = data.frame(grp=sample(letters, 100, TRUE), x=rnorm(100))

Teilen Sie dann nur die relevanten Spalten auf, wenden Sie die scale()Funktion auf x in jeder Gruppe an und kombinieren Sie die Ergebnisse (mit split<-oder ave).

df$z = 0
split(df$z, df$grp) = lapply(split(df$x, df$grp), scale)
## alternative: df$z = ave(df$x, df$grp, FUN=scale)

Dies ist im Vergleich zum Aufteilen von data.frames sehr schnell und das Ergebnis bleibt ohne Iteration für die nachgelagerte Analyse verwendbar. Ich denke die dplyr Syntax ist

library(dplyr)
df %>% group_by(grp) %>% mutate(z=scale(x))

Im Allgemeinen ist diese dplyr-Lösung schneller als das Teilen von Datenrahmen, jedoch nicht so schnell wie das Teilen, Anwenden und Kombinieren.

Martin Morgan
quelle