2015-06-30 6 views
5

Chcę poprawić jedną tabelę na podstawie przesłaniania w innej tabeli. Chcę zmienić wartość w dt_current, gdy dt_override ma tę jednostkę, a zakresy dat pokrywają się z dt_current.Dołączanie dwóch tabel danych w celu nadpisania wartości według zakresu dat

dt_current <- data.table(unit = c(rep("a",10), rep("b", 10)), 
    date = seq(as.Date("2015-1-1"), by = "day", length.out = 10), 
    num = 1:10, key = "unit") 
dt_override <- data.table(unit = c("a", "a", "b", "zed"), start_date = as.Date(c("2015-01-03", "1492-12-25", "2015-01-02", "2015-01-11")), 
    end_date = as.Date(c("2015-01-05", "1492-12-26", "2015-01-04", "2015-01-14")), 
    value = NA, key = "unit") 

Wydaje się, że warto korzystać z jakiejś formy .EACHI podczas łączenia dwóch tabel danych, oznaczonych coś jak poniżej, że to nie działa lub kurs.

dt_current[dt_override, 
    num := if(i.start_date <= date & i.end_date >= date) i.value, 
    by = .EACHI] 

Odpowiedz

6

Korzystanie foverlaps jeden może zrobić

dt_current[, date2 := date] # define end date 
setkey(dt_current, unit, date, date2) # key by unit, start and end dates 
setkey(dt_override, unit, start_date, end_date) # same 

pierwsza opcja, tworzyć i indeksu i aktualizacja przez odniesienie

indx <- foverlaps(dt_override, dt_current, which = TRUE) # run foverlaps and get indices 
dt_current[indx$yid, num := dt_override[indx$xid, value]] # adjust by reference 

Alernatively, można uruchomić foverlaps na odwrót i unikaj tworzenia indx, ale podczas tworzenia zupełnie nowego zbioru danych

foverlaps(dt_current, dt_override)[!is.na(start_date), num := value 
            ][, names(dt_current), with = FALSE] 
2

Oto jeden sposób, wymieniając sekwencje Data:

dt_override[,value:=as.integer(value)] 
# It's necessary to convert to integer because `NA` is logical unless otherwise specified. 

dto = dt_override[,.(
    unit, 
    date = seq.Date(start_date,end_date,by="day"), 
    value 
),by=seq_along(dt_override)][,seq_along:=NULL] 

setkey(dt_current,unit,date) 
dt_current[dto,num:=i.value] 

Teraz foverlaps jest, jest prawdopodobnie znacznie lepszy sposób.

4

Inną alternatywą, używając toczenia dołącza:

setkey(dt_current, unit, date) 
setkey(dt_override, unit, start_date) 

dt_current[, num := dt_override[dt_current, roll = T][end_date >= start_date, 
                 num := value]$num] 

# another version of the above, but using ifelse (unclear to me which one is faster) 
dt_current[, num := dt_override[dt_current, 
           ifelse(end_date >= start_date, value, num), roll = T]] 
+0

To trochę wieje zdanie –