Ich möchte eine neue Spalte in einer Datentabelle erstellen, die aus dem aktuellen Wert einer Spalte und dem vorherigen einer anderen berechnet wird. Ist es möglich, auf vorherige Zeilen zuzugreifen?
Z.B:
> DT <- data.table(A=1:5, B=1:5*10, C=1:5*100)
> DT
A B C
1: 1 10 100
2: 2 20 200
3: 3 30 300
4: 4 40 400
5: 5 50 500
> DT[, D := C + BPreviousRow] # What is the correct code here?
Die richtige Antwort sollte sein
> DT
A B C D
1: 1 10 100 NA
2: 2 20 200 210
3: 3 30 300 320
4: 4 40 400 430
5: 5 50 500 540
r
data.table
Korone
quelle
quelle
DT <- data.table(A=..., key = "A")
Antworten:
Mit der
shift()
Implementierung in Version 1.9.6 ist dies recht einfach.DT[ , D := C + shift(B, 1L, type="lag")] # or equivalently, in this case, DT[ , D := C + shift(B)]
Aus NEWS :
Siehe Antworten für frühere Antworten.
quelle
.N
die aktuelle Zeilennummer oder so? Tut mir leid, hier zu fragen, aber ich kann es nicht in den Hilfedateien finden ....I
nützliche Zeilenindizes für die Zeilen in der aktuellen Gruppe..SD
Beispiel - Ich habe versucht, ein zu verwendenlapply
und funky Ergebnisse zu erhalten. das ist viel einfacher.Mit
dplyr
könnten Sie tun:Welches gibt:
# A B C D #1: 1 10 100 NA #2: 2 20 200 210 #3: 3 30 300 320 #4: 4 40 400 430 #5: 5 50 500 540
quelle
Mehrere Leute haben die spezifische Frage beantwortet. Im folgenden Code finden Sie eine allgemeine Funktion, die ich in solchen Situationen verwende, die hilfreich sein können. Anstatt nur die vorherige Zeile abzurufen, können Sie in der "Vergangenheit" oder "Zukunft" so viele Zeilen verschieben, wie Sie möchten.
rowShift <- function(x, shiftLen = 1L) { r <- (1L + shiftLen):(length(x) + shiftLen) r[r<1] <- NA return(x[r]) } # Create column D by adding column C and the value from the previous row of column B: DT[, D := C + rowShift(B,-1)] # Get the Old Faithul eruption length from two events ago, and three events in the future: as.data.table(faithful)[1:5,list(eruptLengthCurrent=eruptions, eruptLengthTwoPrior=rowShift(eruptions,-2), eruptLengthThreeFuture=rowShift(eruptions,3))] ## eruptLengthCurrent eruptLengthTwoPrior eruptLengthThreeFuture ##1: 3.600 NA 2.283 ##2: 1.800 NA 4.533 ##3: 3.333 3.600 NA ##4: 2.283 1.800 NA ##5: 4.533 3.333 NA
quelle
data.table
Paket zushift
wurde abdata.table
Version 1.9.5 hinzugefügt. Siehe die aktualisierte Antwort von @Arun.Warum nicht einfach, basierend auf dem obigen Kommentar von @Steve Lianoglou:
DT[, D:= C + c(NA, B[.I - 1]) ] # A B C D # 1: 1 10 100 NA # 2: 2 20 200 210 # 3: 3 30 300 320 # 4: 4 40 400 430 # 5: 5 50 500 540
Verwendung und vermeiden
seq_len
oderhead
oder eine andere Funktion.quelle
.I
mitseq_len(.N)
Nach Aruns Lösung können ähnliche Ergebnisse erhalten werden, ohne auf etwas Bezug zu nehmen
.N
> DT[, D := C + c(NA, head(B, -1))][] A B C D 1: 1 10 100 NA 2: 2 20 200 210 3: 3 30 300 320 4: 4 40 400 430 5: 5 50 500 540
quelle
.N
es leicht verfügbar ist) hauptsächlich eine ästhetische Wahl ist. Mir ist kein wichtiger Unterschied bekannt.Ich fügte ein Auffüllargument hinzu, änderte einige Namen und nannte es
shift
. https://github.com/geneorama/geneorama/blob/master/R/shift.Rquelle
Hier ist meine intuitive Lösung:
#create data frame df <- data.frame(A=1:5, B=seq(10,50,10), C=seq(100,500, 100))` #subtract the shift from num rows shift <- 1 #in this case the shift is 1 invshift <- nrow(df) - shift #Now create the new column df$D <- c(NA, head(df$B, invshift)+tail(df$C, invshift))`
Hier
invshift
beträgt die Anzahl der Zeilen minus 1 4.nrow(df)
Sie erhalten die Anzahl der Zeilen in einem Datenrahmen oder in einem Vektor. Wenn Sie noch frühere Werte verwenden möchten, subtrahieren Sie in ähnlicher Weise von nrow 2, 3, ... usw. und setzen Sie die NAs entsprechend am Anfang.quelle
Dies kann in einer Schleife erfolgen.
# Create the column D DT$D <- 0 # for every row in DT for (i in 1:length(DT$A)) { if(i==1) { #using NA at first line DT[i,4] <- NA } else { #D = C + BPreviousRow DT[i,4] <- DT[i,3] + DT[(i-1), 2] } }
Mit einem for können Sie sogar den vorherigen Wert der Zeile dieser neuen Spalte verwenden
DT[(i-1), 4]
quelle