2015-06-28 15 views
18

Mam znacznik czasu w jednej ramce danych, którą próbuję dopasować do najbliższego znacznika czasu w drugiej ramce danych, w celu wyodrębnienia danych z drugiej ramki danych. Zobacz poniżej ogólny przykład mojego podejścia:Dopasowywanie danych czasowych do najbliższego czasu w innym zbiorze danych. Prawidłowo wektoryzowany? Szybszy sposób?

library(lubridate) 

data <- data.frame(datetime=ymd_hms(c('2015-04-01 12:23:00 UTC', '2015-04-01 13:49:00 UTC', '2015-04-01 14:06:00 UTC' ,'2015-04-01 14:49:00 UTC')), 
        value=c(1,2,3,4)) 
reference <- data.frame(datetime=ymd_hms(c('2015-04-01 12:00:00 UTC', '2015-04-01 13:00:00 UTC', '2015-04-01 14:00:00 UTC' ,'2015-04-01 15:00:00 UTC', '2015-04-01 16:00:00 UTC')), 
         refvalue=c(5,6,7,8,9)) 

data$refvalue <- apply(data, 1, function (x){ 
    differences <- abs(as.numeric(difftime(ymd_hms(x['datetime']), reference$datetime))) 
    mindiff <- min(differences) 
    return(reference$refvalue[differences == mindiff]) 
}) 

data 
#    datetime value refvalue 
# 1 2015-04-01 12:23:00  1  5 
# 2 2015-04-01 13:49:00  2  7 
# 3 2015-04-01 14:06:00  3  7 
# 4 2015-04-01 14:49:00  4  8 

Działa to w porządku, oprócz tego, że jest bardzo powolny, ponieważ dataframe odniesienia jest dość duży w mojej aplikacji w świecie rzeczywistym. Czy ten kod jest wektoryzowany? Czy istnieje szybszy, bardziej elegancki sposób wykonywania tej operacji?

+0

W Pythonie jest to dokładnie to, za czym polega funkcja numpy.searchsorted. Szukałem odpowiednika R, ale nie mogę go znaleźć. – cxrodgers

+0

@ cxrodgers: Byłoby interesujące zobaczyć aplikację tej funkcji do tego zadania. Po przejrzeniu dokumentacji, drapię się w głowę, zastanawiając się, jak to zrobić. Czy możesz znaleźć przykład działania SO? –

+0

@BondedDust zobacz odpowiedź udzieloną przez Bi Rico tutaj: http://stackoverflow.com/questions/8914491/finding-the-nearest-value-and-return-index-of-array-in-python – cxrodgers

Odpowiedz

15

Zastanawiałam się, czy będzie to w stanie dopasować data.table rozwiązanie dla prędkości, ale jest to baza-R, które rozwiązanie wektorowy powinien przewyższyć twoją wersję apply. A ponieważ tak naprawdę nigdy nie oblicza odległości, może być rzeczywiście szybszy niż podejście data.table-najbliższego. Dodaje to długość środkowych przedziałów do najniższej możliwej wartości lub punktu początkowego przedziałów, aby utworzyć zbiór "średnich przerw", a następnie wykorzystuje funkcję findInterval do przetwarzania czasów. To tworzy odpowiedni indeks w wierszach zbioru danych reference, a "wartość refurnu" można następnie "przesłać" do obiektu - data.

data$reefvalue <- reference$refvalue[ 
         findInterval(data$datetime, 
            c(-Inf, head(reference$datetime,-1))+ 
            c(0, diff(as.numeric(reference$datetime))/2)) ] 
# values are [1] 5 7 7 8 
+0

Wielkie dzięki. To działa dobrze. – user278411

15

Można spróbować data.table s toczenia sprzężenia za pomocą „najbliższym” opcja

library(data.table) # v1.9.6+ 
setDT(reference)[data, refvalue, roll = "nearest", on = "datetime"] 
# [1] 5 7 7 8 
+1

W jednym line (bez uzyskiwania indeksu): 'setDT (data) [, refvalue: = setkey (setDT (reference), datetime) [dane, refvalue, roll =" nearest "]]' - to będzie znacznie przyjemniejsze, gdy połączy się z nie klucze są zaimplementowane. – Arun

+0

@Arun dzięki, nadal dwa kroki wygląda na bardziej czytelne dla mnie choć ... –

+0

Na pewno. Zgadzam się. – Arun

Powiązane problemy