2012-09-13 4 views
5

Das data.table Paket in R bietet die Option:Bestimmung Zeilenindizes von data.table Gruppenmitgliedern

die: 'true' die Zeilennummern integer kehrt von 'x', dass 'i' Einstimmungen .

Ich sehe jedoch keine Möglichkeit, zu erhalten, innerhalb j, die ganzzahligen Zeilennummern von ‚x‘ innerhalb der Gruppen by Established verwenden.

Zum Beispiel gegeben ...

DT = data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6)) 

... würde Ich mag den Indizes in dem DT für jeden Wert von y kennen.

Der Wert für mich ist, dass ich eine data.table parallel zu einer anderen Datenstruktur (ADS) verwende, zu der ich gruppenweise Berechnungen basierend auf den effizient berechneten Gruppierungen der data.table durchführen möchte.

Zum Beispiel ADS Annahme, daß ein Vektor mit einem Wert für jede Zeile in DT:

ADS<-sample(100,nrow(DT)) 

I kann, wie dieses Problem zu umgehen, berechnet die groupwise Mittelwert der Gruppe von DT $ y bestimmt ADS, wenn I Fügen Sie der data.table zuerst eine neue Sequenzspalte hinzu.

DT[,seqNum:=seq_len(nrow(DT))] 
DT[,mean(ADS[seqNum]),by=y] 

Die gibt das gewünschte Ergebnis auf Kosten einer neuen Spalte.

Mir ist klar, dass in diesem Beispiel habe ich die gleiche Antwort tapply mit bekommen:

tapply(ADS,DT$y,mean) 

Allerdings werde ich dann nicht die Performance-Vorteil von data.tables effiziente Gruppierung bekommen (vor allem, wenn die ‚durch‘ Spalten sind indiziert).

Vielleicht gibt es eine Syntax, die ich übersehe ???

Vielleicht ist dies eine einfache Funktion zu data.table hinzufügen und ich sollte es anfordern (Wink, wink) ???

Proposed Syntax: optional eingestellt '.which' zu dem Gruppenindizes zu schreiben erlaubt:

DT[,mean(ADS[.which]),by=y,which=TRUE] 
+0

Ich fürchte, ich folge nicht. Können Sie ein Beispiel für eine Berechnung angeben, die Sie zwischen ADS und DT ausführen möchten? –

+0

Blau, ich habe ein funktionierendes Beispiel gegeben ... meine letzte Codezeile berechnet den gruppenweisen Mittelwert in ADS mit Indizes von DT. In meiner _real_-Anwendung ist die ADS-Datenstruktur KEIN Vektor, sondern ein "GenomicRanges" -Objekt, und mein DT ist Meta-Daten über die Bereiche. In jedem Fall sind Josh und Matthew, unten, "auf dem Fall". Vielen Dank! – malcook

Antwort

10

Verfügbar seit data.table 1.8.3 Sie .I im j eines data.table bekommen die Zeilenindizes von Gruppen verwenden können ...

DT[ , list(yidx = list(.I)) , by = y ] 
# y yidx 
#1: 1 1,4,7 
#2: 3 2,5,8 
#3: 6 3,6,9 
6

Codierter data.table wird sortiert werden, so dass Gruppen in zusammenhängenden Blöcken gespeichert sind. In diesem Fall könnten Sie .N verwenden, um die gruppenweise Indexierungsinformationen zu extrahieren.

DT <- data.table(x=rep(c("a","b","c"),each=3), y=c(1,3,6)) 
setkey(DT, y) 

ii <- DT[,.N, by=y] 
ii[, start := cumsum(N) - N[1] + 1][,end := cumsum(N)][, N := NULL] 
# y start end 
# 1: 1  1 3 
# 2: 3  4 6 
# 3: 6  7 9 

(Persönlich würde ich wahrscheinlich nur eine Indizierungs Spalte wie Ihre vorgeschlagene seqNum hinzufügen scheint einfacher, glaube ich nicht, es wird die Leistung zu viel beeinflussen, wenn Sie wirklich an die Grenzen treiben.)

+0

+10! Vielleicht will OP. Ich? Zwinker zwinker. –

+0

+11! (Ist das eine Fakultät?) Und, ja, OP (das bin ich) will wirklich '.I' (oder'. which' wenn 'which = TRUE'). Liegt es für die Umsetzung auf dem Tisch? – malcook

+0

@ josh-obrien, ich mag es nicht SeqNum hinzufügen, da davon ausgeht, dass es keine seqNum Spalte bereits verwendet wird, und es ist destruktive Änderung an ein Objekt, das ich nicht ändern möchte. Danke. – malcook