2016-01-13 24 views
7

Jak znajdę ostatnią wartość, przed test.day, dla każdego (loc.x), loc.y parą?Data.Table toczenia dołączyć przez grupy

dt <- data.table( 
    loc.x = as.integer(c(1, 1, 3, 1, 3, 1)), 
    loc.y = as.integer(c(1, 2, 1, 2, 1, 2)), 
    time = as.IDate(c("2015-03-11", "2015-05-10", "2015-09-27", 
        "2015-11-25", "2014-09-13", "2015-08-19")), 
    value = letters[1:6] 
) 

setkey(dt, loc.x, loc.y, time) 
test.day <- as.IDate("2015-10-01") 

Wymagana moc:

loc.x loc.y value 
1:  1  1  a 
2:  1  2  f 
3:  3  1  c 

Odpowiedz

6

Innym rozwiązaniem jest użycie last funkcję:

dt[, last(value[time < test.day]), by = .(loc.x, loc.y)] 

co daje:

loc.x loc.y V1 
1:  1  1 a 
2:  1  2 f 
3:  3  1 c 
+6

Myślę, że 'dt [time

+0

Dziękuję David, dobry punkt – Amitai

6

Możesz pierwszy podzbiór wierszy gdzie time < test.day (co powinno być dość skuteczne, ponieważ nie jest wykonywana przez grupę), a następnie wybierz ostatnią value na grupę. Aby to zrobić można użyć tail(value, 1L) albo, jak sugeruje Floo0, value[.N], powodując:

dt[time < test.day, tail(value, 1L), by = .(loc.x, loc.y)] 
# loc.x loc.y V1 
#1:  1  1 a 
#2:  1  2 f 
#3:  3  1 c 

lub

dt[time < test.day, value[.N], by = .(loc.x, loc.y)] 

Zauważ, że to działa, ponieważ dane są klasyfikowane ze względu na setkey(dt, loc.x, loc.y, time).

+3

Z można użyć 'wartość [.N]' zamiast jeśli tail (wartość 1L) '. – Rentrop

+0

@ Floo0, oczywiście, to inna opcja. –

5

Oto kolejna opcja za pomocą toczenia przystąpić po utworzeniu tabeli odnośników

indx <- data.table(unique(dt[ ,.(loc.x, loc.y)]), time = test.day) 
dt[indx, roll = TRUE, on = names(indx)] 
# loc.x loc.y  time value 
# 1:  1  1 2015-10-01  a 
# 2:  1  2 2015-10-01  f 
# 3:  3  1 2015-10-01  c 

lub bardzo podobną opcję zaproponowaną przez @eddi

dt[dt[, .(time = test.day), by = .(loc.x, loc.y)], roll = T, on = c('loc.x', 'loc.y', 'time')] 

lub jeden wkładki, które będzie mniej wydajny, ponieważ zadzwoni pod numer [.data.table według grupy

dt[, 
    .SD[data.table(test.day), value, roll = TRUE, on = c(time = "test.day")], 
    by = .(loc.x, loc.y) 
    ] 
# loc.x loc.y V1 
# 1:  1  1 a 
# 2:  1  2 f 
# 3:  3  1 c 
+1

Hmm, co powiesz na 'dt [dt [,. (Time = test.day), by =. (Loc.x, loc.y)], roll = T, on = c ('loc.x', 'loc .y ',' time ')] zamiast tego, aby ominąć '[.data.table' w pętli? – eddi

+0

Tak, moja myśl była "indx <- data.table (unique (dt [,. (Loc.x, loc.y)]), time = test.day); dt [indx, roll = TRUE, on = names (indx)] 'faktycznie, ale to wszystko wydaje się być ponad zabiciem i miałem zamiar to usunąć. –

+0

@eddi Dodałem oba do odpowiedzi. Sądzę, że teraz będzie bardziej konkurencyjny. –