2015-08-19 2 views
2

У меня есть этот data.table:Как мы можем выполнить некоторые вычисления, используя последнюю строку внутри группы в data.table в R?

образец:

id cond date 
1 A1 2012-11-19 
1 A1 2013-05-09 
1 A2 2014-09-05 
2 B1 2015-03-05 
2 B1 2015-07-06 
3 A1 2015-02-05 
4 B1 2012-09-26 
4 B1 2015-02-05 
5 B1 2012-09-26 

Я хочу, чтобы рассчитать просроченные дни с сегодняшнего дня в каждой группе «ид» и «Cond», так что я пытаюсь получить разница дней между последней датой в каждой группе и sys.date. Желаемый вывод:

id cond date  overdue 
1 A1 2012-11-19 NA 
1 A1 2013-05-09 832 
1 A2 2014-09-05 348 
2 B1 2015-03-05 NA 
2 B1 2015-07-06 44 
3 A1 2015-02-05 195 
4 B1 2012-09-26 NA 
4 B1 2015-02-05 195 
5 B1 2012-09-26 1057 

Я пытался добиться этого, следующий код:

sample <- sample[ , overdue := Sys.Date() - date[.N], by = c('id','cond')] 

Но я получаю следующий вывод, где значение имеют рециркуляции:

id cond date  overdue 
1 A1 2012-11-19 832 
1 A1 2013-05-09 832 
1 A2 2014-09-05 348 
2 B1 2015-03-05 44 
2 B1 2015-07-06 44 
3 A1 2015-02-05 195 
4 B1 2012-09-26 195 
4 B1 2015-02-05 195 
5 B1 2012-09-26 1057 

Я не уверен, как могу ли я ограничить свой код просто выполнением вычислений для последней строки и не переработкой. Я уверен, что были бы способы сделать это, помощь приветствуется.

ответ

5

Вы можете сделать таблицу просроченных значений и строки они принадлежат:

bycols = c("id","cond") 
newcolDT2 = DT[, Sys.Date() - date[.N], by = bycols] 

DT[newcolDT2, overdue := V1, on = bycols, mult = "last"] 
# id cond  date overdue 
# 1: 1 A1 2012-11-19 NA days 
# 2: 1 A1 2013-05-09 832 days 
# 3: 1 A2 2014-09-05 348 days 
# 4: 2 B1 2015-03-05 NA days 
# 5: 2 B1 2015-07-06 44 days 
# 6: 3 A1 2015-02-05 195 days 
# 7: 4 B1 2012-09-26 NA days 
# 8: 4 B1 2015-02-05 195 days 
# 9: 5 B1 2012-09-26 1057 days 

Это (возможно, уродливее) версия однострочника:

DT[J(unique(DT[, bycols, with=FALSE])), 
    overdue := Sys.Date() - date, on = bycols, mult = "last"] 

данные :

DT <- data.table(read.table(header=TRUE,text="id cond date 
1 A1 2012-11-19 
1 A1 2013-05-09 
1 A2 2014-09-05 
2 B1 2015-03-05 
2 B1 2015-07-06 
3 A1 2015-02-05 
4 B1 2012-09-26 
4 B1 2015-02-05 
5 B1 2012-09-26"))[, date := as.IDate(date)] 

# anyone know how to do this with fread()? 
+1

Спасибо, Франк для ответа и информации о версии для использования «на». – nsDataSci

3

Во-первых, извлечь строки, которые вы заинтересованы в, а затем присвоить значения:

rows = DT[, .I[.N], by = .(id, cond)]$V1 
DT[rows, overdue := Sys.Date() - date] 

DT 
# id cond  date overdue 
#1: 1 A1 2012-11-19 NA days 
#2: 1 A1 2013-05-09 832 days 
#3: 1 A2 2014-09-05 348 days 
#4: 2 B1 2015-03-05 NA days 
#5: 2 B1 2015-07-06 44 days 
#6: 3 A1 2015-02-05 195 days 
#7: 4 B1 2012-09-26 NA days 
#8: 4 B1 2015-02-05 195 days 
#9: 5 B1 2012-09-26 1057 days 
+1

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

+0

Спасибо, Eddi. Это именно то, что мне нужно. – nsDataSci

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