2014-02-17 4 views
7

für eine data.Table-DT nach Standort gruppiert, sortiert nach Zeitpunkt t, ich muss den letzten Wert einer Variablen in jeder Gruppe ändern. Ich nehme an, dass es möglich sein sollte, dies durch Verweis zu tun mit: =, aber ich habe noch keinen Weg gefunden, der funktioniert.Wie der letzte Wert in jeder Gruppe durch Verweis in data.table

Beispieldaten:

require(data.table) # using 1.8.11 
DT <- data.table(site=c(rep("A",5), rep("B",4)),t=c(1:5,1:4),a=as.double(c(11:15,21:24))) 
setkey(DT, site, t) 
DT 
# site t a 
# 1: A 1 11 
# 2: A 2 12 
# 3: A 3 13 
# 4: A 4 14 
# 5: A 5 15 
# 6: B 1 21 
# 7: B 2 22 
# 8: B 3 23 
# 9: B 4 24 

Das gewünschte Ergebnis ist den letzten Wert von a in jeder Gruppe zum Beispiel sieht auf 999, so dass das Ergebnis wie, zu ändern:

# site t a 
# 1: A 1 11 
# 2: A 2 12 
# 3: A 3 13 
# 4: A 4 14 
# 5: A 5 999 
# 6: B 1 21 
# 7: B 2 22 
# 8: B 3 23 
# 9: B 4 999 

Es scheint, wie .I und/oder .N sollten verwendet werden, aber ich habe kein funktionierendes Formular gefunden. Die Verwendung von: = in derselben Anweisung wie .I [.N] gibt einen Fehler. Im Folgenden gibt mir die Zeilennummern, bei denen die Zuordnung vorgenommen werden soll:

DT[, .I[.N], by=site] 
# site V1 
# 1: A 5 
# 2: B 9 

aber ich scheine nicht in der Lage sein, dies zu verwenden, um mit einer: = Zuordnung. Die folgenden geben Fehler:

DT[.N, a:=999, by=site] 
# Null data.table (0 rows and 0 cols) 

DT[, .I[.N, a:=999], by=site] 
# Error in `:=`(a, 999) : 
# := and `:=`(...) are defined for use in j, once only and in particular ways. 
# See help(":="). Check is.data.table(DT) is TRUE. 

DT[.I[.N], a:=999, by=site] 
# Null data.table (0 rows and 0 cols) 

Gibt es eine Möglichkeit, dies in data.table durch Bezugnahme zu tun? Oder ist das besser anders in R gemacht?

Antwort

13

Aktuell können Sie

DT[DT[,.I[.N],by=site][['V1']],a:=999] 
# or, avoiding the overhead of a second call to `[.data.table` 
set(DT, i = DT[,.I[.N],by='site'][['V1']], j = 'a', value = 999L) 

alternative Ansätze verwenden:

Verwendung replace ...

DT[, a := replace(a,seq_len(.N)==.N,999) ,by=site] 

oder den Ersatz der RHS verschieben, eingewickelt durch {} und gibt den vollständigen Vektor

DT[,a:={a[.N]<-999L; a},by=site] 

oder mult='last' verwenden und by-without-by nutzen. Dies erfordert, dass die data.table von den Interessengruppen codiert wird.

DT[unique(site),a:=999,mult='last'] 

Es gibt eine Feature-Anfrage #2793 die

DT[, a[.N] := 999] 

erlauben würde, aber das ist noch

+1

Danke für 4 Lösungen @mnel umgesetzt werden. +1 für [FR # 2793] (https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2793&group_id=240&atid=978), das wird eindeutig eine elegante Art sein, dies zu kodieren , wenn implementiert. –

+0

@DouglasClark - 5. Lösung veröffentlicht. FR # 2793 wäre am schönsten! – mnel

+0

Wow. Ich habe die "{}" RHS-Syntax vorher nicht gesehen. Vermutlich könnte man eine ganze Reihe von Operationen innerhalb der {} im Kontext der Gruppe ausführen, solange die letzte Übereinstimmung der Länge und des Typs von LHS entspricht. Sortieren Sie beispielsweise die Spalte und legen Sie dann sowohl das erste als auch das letzte Element in jeder Gruppe fest: DT [, a: = {a <-sort (a, abnehmend = T); a [1] <- 888; a [.N] <- 999; a}, durch = Site]. Wenn 'a' innerhalb von {} indiziert werden kann, scheint dies bereits vieles zu ermöglichen, was FR # 2793 erreichen würde. –

Verwandte Themen