2016-03-22 7 views
-1

Ich möchte ein Beispiel für Zeilen, die einen bestimmten Wert enthalten, mit einer Grenze von 3 Zeilen pro Wert beibehalten.Keep x Anzahl der Zeilen mit dem gleichen Wert

Zum Beispiel sagen, dass ich maximal 3 Zeilen pro Farbe behalten möchten:

X1   X2 
1 0.7091409 RED 
2 -1.1334614 BLUE 
3 2.3343391 RED 
4 -0.9040278 GREEN 
5 0.4180331 RED 
6 0.7572246 RED 
7 -0.8996483 BLUE 
8 -1.0356774 BLUE 
9 -0.3983045 GREEN 
10 -0.9060305 BLUE 

Hier in Spalte X2 erscheint RED 4 mal, erscheint BLUE 4-mal, und GRÜN erscheint 2-mal. Ich möchte die Zeilen trimmen, um maximal 3 Zeilen zu behalten, die einen bestimmten Wert in Spalte X2 enthalten. So würde der obige Datensatz werden:

X1   X2 
1 0.7091409 RED 
2 -1.1334614 BLUE 
3 2.3343391 RED 
4 -0.9040278 GREEN 
5 0.4180331 RED 
6 -0.8996483 BLUE 
7 -1.0356774 BLUE 
8 -0.3983045 GREEN 

Irgendwelche Ideen, wie man das erreicht?

+0

[siehe hier] (http://stackoverflow.com/questions/34753050/data-table-select-first-n-rows-within-group) für eine Lösung mit * data.table * – Jaap

Antwort

0

Hier ist eine Basis R-Lösung mit split in Gruppen aufgeteilt, basierend auf X2, mapplysample zu den verschiedenen Gruppen anzuwenden und pmin die Probengrößen für jede Gruppe zu erhalten.

library(splitstackshape) 
stratified(d, "X2", size = pmin(lengths(split(d$X1, d$X2)), 3)) 

Diese Lösung funktioniert, wenn es mehr als die beiden Spalten in der Probe enthalten:

d2 <- split(d$X1, d$X2) 
stack(mapply(sample, d2, pmin(lengths(d2), 3))) 

Eine alternative Lösung könnte stratified vom splitstackshape Paket zu verwenden sein.


Edit:

Griff mehr als zwei Spalten der Basis R Antwort oben. Wenn alle Werte in X1 einzigartig sind, können Sie einfach fusionieren (LEFT JOIN) die abgetasteten Daten mit den Originaldaten der ausfüllen: Sonst

sampled_d <- stack(mapply(sample, d2, pmin(lengths(d2), 3))) # same as base solution above 
merge(sampled_d, d, 
    by.x = c("values", "ind"), 
    by.y = c("X1", "X2"), 
    all.x = TRUE) # left join 

könnte die Basislösung der folgenden hässlichen Code angepasst werden:

d3 <- split(d, d$X2) 
do.call(rbind, 
    mapply(function(ii, jj) ii[sample(nrow(ii), jj), ], 
     d3, 
     pmin(lapply(d3, function(ii) dim(ii)[1]), 3), 
     SIMPLIFY = FALSE)) 

Beispieldaten:

d <- read.table(text=" 
    X1   X2 
1 0.7091409 RED 
2 -1.1334614 BLUE 
3 2.3343391 RED 
4 -0.9040278 GREEN 
5 0.4180331 RED 
6 0.7572246 RED 
7 -0.8996483 BLUE 
8 -1.0356774 BLUE 
9 -0.3983045 GREEN 
10 -0.9060305 BLUE", header=TRUE) 
+0

Dank @ Jota. Die ursprünglichen Daten, mit denen ich arbeite, haben jedoch 16 Spalten. Kann diese Methode für mehr als 2 Spalten implementiert werden? Mir ist nicht klar, wie. – jds7117

0

ich glaube this solution für mich gearbeitet.

# install.package(data.table) # if necessary 
library(data.table) 
# convert my dataframe (df2) to a datatable 
DT <- data.table(df2) 

Dann hat die Funktion, die ein Maximum von 3 Reihen für eine Gruppe mit einem Wert in der Spalte ‚X2‘ definiert hält.

DT2 <- DT[, head(.SD, 3), by = "X2"] 
+0

Wenn eine Zufallsstichprobe wichtig ist, nur eine Anmerkung, dass "Kopf" die ersten 3 oder weniger Beobachtungen für jede Gruppe macht, keine zufällige Stichprobe. Wenn eine zufällige Stichprobe wichtig ist, müssen Sie die Lösung an etwas anpassen: 'DT [, lapply (.SD, Beispiel, pmin (dim (.SD) [1], 3)), by =" X2 "] ' – Jota

Verwandte Themen