Chcę utworzyć nową kolumnę w tabeli data.table obliczoną na podstawie bieżącej wartości jednej kolumny i poprzedniej w drugiej. Czy jest możliwy dostęp do poprzednich rzędów?
Na przykład:
> 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?
Prawidłowa odpowiedź powinna brzmieć
> 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
źródło
źródło
DT <- data.table(A=..., key = "A")
Odpowiedzi:
Po
shift()
zaimplementowaniu w wersji 1.9.6 jest to dość proste.DT[ , D := C + shift(B, 1L, type="lag")] # or equivalently, in this case, DT[ , D := C + shift(B)]
Z WIADOMOŚCI :
Zobacz historię poprzednich odpowiedzi.
źródło
.N
aktualny numer wiersza czy coś? Przepraszam, że pytam, ale nie mogę go znaleźć w plikach pomocy ....I
przechowywanie indeksów wierszy dla wierszy w bieżącej grupie..SD
przykład +1 - próbowałem użyć alapply
i otrzymałem fajne wyniki. to jest dużo prostsze.Używając
dplyr
możesz zrobić:Co daje:
# 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ódło
Kilka osób odpowiedziało na konkretne pytanie. Zobacz poniższy kod, aby zapoznać się z funkcją ogólnego przeznaczenia, której używam w takich sytuacjach, która może być pomocna. Zamiast pobierać tylko poprzedni wiersz, możesz przejść do dowolnej liczby wierszy w „przeszłości” lub „przyszłości”.
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
źródło
data.table
shift
została dodanadata.table
w wersji 1.9.5. Zobacz zaktualizowaną odpowiedź od @Arun.Na podstawie powyższego komentarza @Steve Lianoglou, dlaczego nie tylko:
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
I unikaj używania
seq_len
lubhead
lub jakiejkolwiek innej funkcji.źródło
.I
goseq_len(.N)
Po rozwiązaniu Arun podobne wyniki można uzyskać bez odwoływania się do
.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
źródło
.N
jest łatwo dostępny) jest to głównie wybór estetyczny. Nie znam żadnej istotnej różnicy.Dodałem argument wypełniający, zmieniłem kilka nazw i nazwałem go
shift
. https://github.com/geneorama/geneorama/blob/master/R/shift.Rźródło
Oto moje intuicyjne rozwiązanie:
#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))`
Tutaj
invshift
liczba wierszy pomniejszona o 1 wynosi 4.nrow(df)
zapewnia liczbę wierszy w ramce danych lub w wektorze. Podobnie, jeśli chcesz wziąć jeszcze wcześniejsze wartości, odejmij od nrow 2, 3, ... itd., A także umieść odpowiednio NA na początku.źródło
można to zrobić w pętli.
# 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] } }
Używając for, możesz nawet użyć poprzedniej wartości wiersza tej nowej kolumny
DT[(i-1), 4]
źródło