2016-03-16 4 views
2

У меня есть таблица газовых дозаправок, a, как это:подсчет прошло дней от непоследовательных таблицы

a = setDT(structure(list(date = structure(c(NA, 16837, 16843, 16847, 16852, 
16854, 16858, 16862, 16867, 16871, 16874), class = "Date"), km = c(NA, 
NA, 421, 351, 286, 350, 414, 332, 401, 321, 350)), .Names = c("date", 
"km"), class = c("data.table", "data.frame"), row.names = c(NA, 
-11L)), key = "date") 

Это дата дозаправки и км ехало с этой дозаправкой. Я также дал другую таблицу с датами давления в шинах регулировочных и заменой масла, actions, как это:

actions = setDT(structure(list(date = structure(c(16841, 16843, 16858, 16869), class = "Date"), 
    action = structure(c(1L, 2L, 2L, 2L), .Label = c("oil", "tires" 
    ), class = "factor")), .Names = c("date", "action"), row.names = c(NA, 
-4L), class = c("data.table", "data.frame")), key = "action") 

мне нужно связать расход топлива (в реальной версии a У меня также есть галлон), чтобы дней, прошедших с момента последней проверки давления в шинах и после последней замены масла. Должен быть простой способ добиться этого, но через несколько часов я застрял.

Это то, что я пробовал:

library(data.table) 
library(lubridate) 
library(reshape2) 

b <- dcast(actions, date ~ action, value.var = "date") 

d <- seq(min(a$date, b$date, na.rm = TRUE), max(a$date, b$date, na.rm = TRUE), by = "day") 
d <- data.table(date=d) 
d <- b[d,] 
d$daysOil <- as.double(difftime(d$date, d$date[! is.na(d$oil)], units = "days")) 
d$daysOil[which(d$daysOil < 0)] <- NA 

Дела становится намного сложнее, если я пытаюсь вычислить количество дней, прошедших с момента последней «шина» событие (тот, который ближе перед тем дата дозаправки), и вот где я застрял.

Мой ожидается выход:

expected 
     date km daysoil daysTires 
1  <NA> NA  NA  NA 
2 2016-02-06 NA  NA  NA 
3 2016-02-12 421  2   0 
4 2016-02-16 351  6   4 
5 2016-02-21 286  11   9 
6 2016-02-23 350  13  11 
7 2016-02-27 414  17   0 
8 2016-03-02 332  21   4 
9 2016-03-07 401  26   9 
10 2016-03-11 321  30   2 
11 2016-03-14 350  33   5 

Я ценю любое решение, но предпочтительно с использованием data.table или dplyr пакетов.

########## ########## EDIT

Если вы можете думать о лучшей информации (таблицы) структуры, чтобы облегчить эту задачу, она будет высоко ценится!

ответ

2

Вот один вариант:

actions[, date.copy := date] 

cbind(a, 
     dcast(actions[, .SD[a, .(days = date - date.copy, N = .I), roll = T, on = 'date'] 
        , by = action], 
      N ~ action, value.var = 'days')) 
#   date km N  oil tires 
# 1:  <NA> NA 1 NA days NA days 
# 2: 2016-02-06 NA 2 NA days NA days 
# 3: 2016-02-12 421 3 2 days 0 days 
# 4: 2016-02-16 351 4 6 days 4 days 
# 5: 2016-02-21 286 5 11 days 9 days 
# 6: 2016-02-23 350 6 13 days 11 days 
# 7: 2016-02-27 414 7 17 days 0 days 
# 8: 2016-03-02 332 8 21 days 4 days 
# 9: 2016-03-07 401 9 26 days 9 days 
#10: 2016-03-11 321 10 30 days 2 days 
#11: 2016-03-14 350 11 33 days 5 days 

Несколько простых вещей, которые идут в выше - бежать в части, чтобы понять.

+0

Удивительный один лайнер. Понадобились бы годы, чтобы придумать что-то подобное, спасибо! Кажется, что 'data.table' (и R вообще) всегда имеет скрытый камень для меня. На этот раз был «roll = TRUE». – PavoDive

Смежные вопросы