2012-11-29 13 views
6

Ich habe einen sehr großen Datenrahmen, den ich gerne eine Teilmenge von basierend auf einer bestimmten Teilmenge eines Vektors speichern würde. Kurz gesagt: Ich habe so etwas wie dies:Indizierung eines Datenrahmens basierend auf einer Vektoruntermenge

> id<-c("ID1","ID2","ID2","ID3","ID4","ID4","ID4","ID4","ID4") 
> status<-c("flag","flag","none","none","flag","flag","flag","none","flag") 
> misc1ofmany<-c("etc1","etc2","etc3","etc4","etc5","etc6","etc7","etc8","etc9") 
> df = data.frame(id, status, misc1ofmany) ; df 
    id status misc1ofmany 
1 ID1 flag  etc1 
2 ID2 flag  etc2 
3 ID2 none  etc3 
4 ID3 none  etc4 
5 ID4 flag  etc5 
6 ID4 flag  etc6 
7 ID4 flag  etc7 
8 ID4 none  etc8 
9 ID4 flag  etc9 

Ich mag würde alle Zeilen von IDs haben, die gekennzeichnet wurden, einschließlich ihrer nicht-gekennzeichneten Sitzungen. Im Moment versuche ich, den Index der anderen IDs durch grep zu erhalten und diesen wieder in ein neues df zu stecken. Eigentlich, wie ich dies aus schrieb ich herausgefunden, dass Grepl könnte einfacher sein, mit zu arbeiten:

> flaggedIDs <- unique(as.vector(df$id[grep("flag",df$status)])) 
> flaggedIDs.allStats.Index <- mapply(grepl,df$id,MoreArgs=list(x=flaggedIDs)) 
> flaggedIDs.allStats.Index 
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
[1,] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[2,] FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE 
[3,] FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE 

aber ich will nur hier bekommen:

> flaggedIDsdf <- df[flaggedIDs.allStats.Index] ; flaggedIDsdf 
    id status misc1ofmany 
1 ID1 flag  etc1 
2 ID2 flag  etc2 
3 ID2 none  etc3 
4 ID4 flag  etc5 
5 ID4 flag  etc6 
6 ID4 flag  etc7 
7 ID4 none  etc8 
8 ID4 flag  etc9 

ich so fühlen sollte einfacher sein, als ich Ich mache das aus, aber ich habe eine Reihe von Möglichkeiten ausprobiert, um das herauszufinden, ohne Erfolg. das Schreiben der Frage half mir dabei, zu einem klareren/einfacheren Problem in meinem Kopf zu werden (es sieht so aus, als ob ich jetzt nur einen Schritt verpasse), aber jetzt frage ich mich auch, ob es einen effizienteren Weg gibt, dies zu tun.

Antwort

6

data.table ist hier wirklich nützlich für seine elegante Syntax und Speichereffizienz

library(data.table) 

DT <- data.table(df) 

setkey(DT, 'id') 

DT[DT[status=='flag', list(id = unique(id))]] 

    id status misc1ofmany 
1: ID1 flag  etc1 
2: ID2 flag  etc2 
3: ID2 none  etc3 
4: ID4 flag  etc5 
5: ID4 flag  etc6 
6: ID4 flag  etc7 
7: ID4 none  etc8 
8: ID4 flag  etc9 

Oder noch kompakter

DT[J(unique(id[status=='flag']))] 

Diese beiden Ansätze über die Verwendung der Tatsache, dass die i Komponente zuerst von data.table ausgewertet . Keying von id bedeutet, dass wir einen Self-Join durchführen können, um nur diejenigen zu extrahieren ids wo status=='flag.


Oder by

DT[,if(any(status=='flag')){.SD} ,by=id] 

unter Verwendung dieser geht durch die Untergruppen von DT von id und gibt .SD (die data.table der Teilmenge), wenn any(status=='flag') (innerhalb dieser Untergruppe).

+0

sehr elegant! Danke für die Antwort! – stites

1

Ich glaube, was Sie versuchen, in einer Zeile behandelt tun können

df[which(df$id %in% df$id[df$status=="flag"]), ] 

Ergebnis:

id status misc1ofmany 
1 ID1 flag  etc1 
2 ID2 flag  etc2 
3 ID2 none  etc3 
5 ID4 flag  etc5 
6 ID4 flag  etc6 
7 ID4 flag  etc7 
8 ID4 none  etc8 
9 ID4 flag  etc9 
+0

Er scheint die ID und die Zeilen so lange zu behalten, wie sie markiert sind. Dies hält nur diejenigen, die markiert sind. –

+0

@Brandon Woops! Danke für die Klärung, Ill ändern –

2

Dies scheint zu funktionieren:

df[df$id %in% df$id[df$status == "flag"],] 

Plain Englisch: aus Wählen Sie im Datenrahmen jede Zeile aus, deren ID-Element sich im Vektor der ID-Elemente befindet, deren Status in einer beliebigen Zeile markiert ist.

Verwandte Themen