2017-02-02 1 views
0

Ich versuche dplyr oder DT zu verwenden, um zu bestimmen, ob nach dem ersten Auftreten eines Werts nachfolgende Werte kleiner als der angegebene Wert sind.Suche nach Werten, die kleiner als das erste Vorkommen eines Werts sind

Wenn ich also einen Datenrahmen habe, wie unten,

df2 <- data.frame(id=c(1,1,1,1,1,2,2,2,2,3,3,3,3,3,3), 
      num=c(1,2,1,1,2,1,1,1,2,2,1,1,1,2,2)) 
df2$id <- as.factor(df2$id) 

Ich mag die ids finden, die das Auftreten von weniger als 2 nach dem ersten Auftreten von 2. Zum Beispiel haben, würde dies abholen ID 1 , da es eine 2 in der zweiten Zeile gibt, aber für diese ID gibt es nachfolgende Zeilen weniger als 2).

Irgendwelche Ideen?

+0

Ich bin sicher, ich muss irgendwie() irgendwie verwenden, aber ich bin. Es ist sicher, wie – user85727

Antwort

4

Sounds wie ein Job für ?Position zu mir, obwohl ich nicht sicher bin, welche Ausgabe Sie genau wollen:

library(data.table) 
setDT(df2) 
df2[, Position(I,num==2) < Position(I,num < 2,right=TRUE,nomatch=FALSE), by=id] 
# id V1 
#1: 1 TRUE 
#2: 2 FALSE 
#3: 3 TRUE 

df2[, Position(I,num==2) < Position(I,num < 2,right=TRUE,nomatch=FALSE), by=id][,id[V1]] 
#[1] 1 3 
#Levels: 1 2 3 
+0

Danke, hatte noch nie von dieser Funktion gehört. – user85727

+0

Wo befindet sich die Position? – user85727

+0

@ user85727 - Wenn Sie "? Position" in die R-Konsole eingeben, wird die Hilfe für 'Position()' (und eine Reihe weiterer nützlicher funktionaler Programmierfunktionen) angezeigt. – thelatemail

3

Eine Lösung mit data.table. Btw in Ihrem Beispiel Ids 1 und 3 sollte als id 3 beginnt mit einem 2 und der nächste Wert ist 1.

#first chain removes all rows for each group up to and including the first 2 
#second chain returns the unique ids if a number less than 2 occurs 
setDT(df2)[, .SD[-(1:which(num == 2)[1]), ], by = 'id'][which(num < 2), .(id = unique(id))] 

Ausgang gewählt werden:

id 
1: 1 
2: 3 

df2

> df2 
    id num 
1: 1 1 
2: 1 2 
3: 1 1 
4: 1 1 
5: 1 2 
6: 2 1 
7: 2 1 
8: 2 1 
9: 2 2 
10: 3 2 
11: 3 1 
12: 3 1 
13: 3 1 
14: 3 2 
15: 3 2 
2

Hier ist eine Basis-R-Version, die die Split-Apply-Methode verwendet.

levels(df2$id)[sapply(split(df2$num, df2$id), 
         function(i) if(any(tail(i, -which.max(i==2)) < 2)) TRUE else FALSE)] 
[1] "1" "3" 

I verwendet levels um sicherzustellen, dass der Auftrag split folgen würde. Die Entscheidungsfunktion in if verwendet any für einen Vergleich einer abgeschnittenen Version des Vektors, der unter Verwendung von tail und which.max geschnitten wird.

Verwandte Themen