2016-04-22 13 views
0

Der Arbeitsdatensatz wie folgt aussieht:Erstellen von Gruppen mit data.table

library('data.table') 
df <- data.table(Name = c("a","a","b","b","c","c","d","d","e","e","f","f"), 
       Y = sample(1:30,12), 
       X = sample(1:30,12)) 

df 
    Name Y X 
1: a 14 23 
2: a 19 18 
3: b 10 16 
4: b 23 11 
5: c 2 12 
6: c 12 24 
7: d 8 14 
8: d 26 2 
9: e 16 26 
10: e 6 4 
11: f 29 28 
12: f 28 30 

Was ich will, schließlich ist Graph von Gruppen zu machen (basierend auf Name) zum Vergleich:

library(ggplot2) 
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ Name) 

Da die tatsächlichen Datensatz enthält viel mehr Beobachtungen und grp. Der ggplot, den ich erstelle, benötigt zu viel Zeit für die Verarbeitung und der letzte Graph ist nicht lesbar (grp> 300). Ich plane, die Daten mit einer begrenzten Anzahl von Beobachtungen neu zu gruppieren und sie getrennt zu graphisieren (z. B. jedes Mal 10 Gruppen).

Also das letzte Daten-Set sollte wie folgt aussieht:

Name Y X grp level 
1: a 14 23 1  1 
2: a 19 18 1  1 
3: b 10 16 2  1 
4: b 23 11 2  1 
5: c 2 12 3  1 
6: c 12 24 3  1 
7: d 8 14 4  2 
8: d 26 2 4  2 
9: e 16 26 5  2 
10: e 6 4 5  2 
11: f 29 28 6  2 
12: f 28 30 6  2 

und dann kann ich die grafische Darstellung ausführen basierend auf der neuen Gruppe level:

ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ level) 

In der obigen Abbildung, habe ich die grp einfach von:

df[, grp := .GRP, by = Name] 

Die Frage ist jetzt wie Erstellen Sie die level Gruppe automatisch basierend auf grp (ich muss grp anstelle von Name direkt als Basis erstellen, da im ursprünglichen Datensatz gibt es keine Muster in Name)?

habe ich versucht, so etwas wie:

setkey(df, grp) 
i <- 1 
j <- 1 
while(i < 4) { 
    df[levels(factor(grp)) == (i:i+2), level := j] 
    i <- i + 2 
    j <- j + 1 
} 

Es ist nicht gut funktioniert, wie ich brauche. Kann mir jemand einen Rat geben, wie ich dieses Problem angehen kann? Ich bin wirklich fest hier. Ich denke, es könnte eine einfache Möglichkeit sein, dies zu tun, vielleicht muss ich nicht einmal die level Gruppe erstellen und kann die separate Grafik direkt mit anderen Mitteln erstellen?

+1

'level' ist nur' grp' 'cut' in Stücke von 3, richtig? – rawr

+0

@rawr ja, ich gebe nur ein Beispiel dort. In der Abbildung hat 'grp' 6 Ebenen, ich möchte sie nur auf 2 Ebenen reduzieren, jede 'Ebene' enthält 1 ~ 3 Ebenen in' grp'. – Chuan

+0

also 'df [, level: = as.numeric (cut (grp, breaks = 2))]'? – rawr

Antwort

1

Wenn gibt es nur wenige Gruppen, die fct_collapse() Funktion aus dem forcats Paket verwendet werden. Es ermöglicht das einfache Zusammenfassen von Faktorstufen in manuell definierte Gruppen.

Durch diese kann die neue Variable level direkt erstellt werden, ohne einen Umweg über Gruppennummern und cut() zu machen. Und den Ebenen können aussagekräftige Beschriftungen zugewiesen werden.

library('data.table') 
df <- data.table(Name = rep(letters[1:6], each = 2), 
       Y = sample(1:30,12), 
       X = sample(1:30,12)) 
df[, level := forcats::fct_collapse(Name, "a-c" = letters[1:3], "d-e" = letters[4:6])] 
df 
# Name Y X level 
# 1: a 11 13 a-c 
# 2: a 29 12 a-c 
# 3: b 16 5 a-c 
# 4: b 12 6 a-c 
# 5: c 25 28 a-c 
# 6: c 27 11 a-c 
# 7: d 5 9 d-e 
# 8: d 23 20 d-e 
# 9: e 13 26 d-e 
#10: e 17 19 d-e 
#11: f 19 8 d-e 
#12: f 22 3 d-e 

Jedoch erwähnte die OP, dass es viele Gruppen (df[, uniqueN(Name)] > 300) und das er will die Daten mit begrenzten Anzahl von Beobachtungen wieder Gruppe. Die Verwendung von cut() in der in this comment vorgeschlagenen Weise kann zu unbefriedigenden Ergebnissen führen.

Um dies demonstrieren wir einen größeren Probendatensatz von 100 Zeilen erstellen müssen:

N <- 100 
set.seed(1234) 
df <- data.table(Name = sample(letters, N, replace = TRUE), 
       Y = sample(seq.int(3*N), N), 
       X = sample(seq.int(3*N), N)) 
df 

Beachten Sie, dass set.seed() die Daten reproduzierbar zu machen, verwendet wird.

Nun wird die Anzahl der eindeutigen Werte von Name (die grp zu OPs entspricht) wird in 6 Stufen aufgeteilt und aufgezeichnet in Facetten (folgenden this comment):

n_lvls <- 6 
df[, level := as.numeric(cut(as.integer(factor(Name)), breaks = n_lvls))] 
ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ level) 

enter image description here

Hier Facette 3 enthält nur wenige Datenpunkte, während andere Facetten ziemlich überfüllt erscheinen.


Um dies zu überwinden, können die Werte, die etwa die gleiche Anzahl von Datenpunkten statt der gleichen Anzahl von Faktorstufen enthalten angeordnet:

lvls <- df[, .N, by = Name][order(-N), level := cut(cumsum(N), n_lvls, labels = FALSE)] 
df <- lvls[df, on = "Name"] 

ggplot(df, aes(X, Y)) + geom_point() + facet_grid(. ~ level) 

enter image description here

Jetzt, Die Beobachtungen sind gleichmäßiger auf die Facetten verteilt.

Der Code zählt die Anzahl der Beobachtungen pro Name, sortiert in der Reihenfolge der N absteigend verwendet cut() auf der kumulativen Summe der Beobachtungen eine data.table lvls OFTHE neue Ebene zu schaffen. Schließlich sind die neuen Ebenen richtig mit dem ursprünglichen Datensatz df verbunden.