开始日期到结束日期的日期差异

4
我有一些数据,看起来像下面这样。
id   from data   to date
1   2015-03-09   2015-03-14
2   2015-02-22   2015-02-24
2   2015-05-06   2015-05-17
3   2015-02-12   2015-02-16
4   2015-03-10   2015-03-16
4   2015-03-22  2015-04-07
4   2015-06-07  2015-07-07
4   2015-07-06   2015-07-07
4   2015-08-02   2015-08-07

我想创建一个单独的变量,该变量是按id分组的两个日期之间的差异。每个id的第一次将为NA。我尝试了以下方法,基于stackoverflow上的其他答案,但我无法实现。

library(data.table)
chf1 = data.table(id = chf$id,from date = chf$f.date,to_date = chf$t.date)
setkey(chf1,id)
chf1[,diff:=c(NA,difftime(from_date, to_date, units = "days")),by=id]

输出结果如下:
id   from_date   to_date      difference
1   2015-03-09   2015-03-14     NA
2   2015-02-22   2015-02-24     NA
2   2015-05-06   2015-05-17     71
3   2015-02-12   2015-02-16     NA
4   2015-03-10   2015-03-16     NA
4   2015-03-22  2015-04-07      6
4   2015-06-07  2015-06-10      64
4   2015-07-06   2015-07-07     26
4   2015-08-02   2015-08-07     26

我认为你需要使用 chf1[,diff:=difftime(from_date, to_date, units = "days"),by=id]chf1$from_date 获取整个列,按 'id' 分组不会产生任何效果。另外,diff 需要将 NA 或 0 或其他值附加到输出中,而不是 difftime - akrun
我理解这个错误。但是在将chf1$from_date更改为from_date后,我无法达到预期的输出。 - ssan
因为您已经更改了值,请从“data.table”创建步骤运行。 - akrun
为什么在一个记录的“to_date”列中,您的输入和期望输出具有不同的值? - Ronak Shah
1个回答

6

代码存在三个问题:

1) chf1$from_datechf1$to_date获取整个列,因此按'id'分组没有任何效果。

2) difftime返回的结果与初始列长度相同。

3) 由于difftime对'from_date'的每个元素与对应的'to_date'元素之间的差值进行了操作,因此不需要使用by = id

因此,代码可以被改写为:

chf1[, diff1:=difftime(from_date, to_date, units = "days")]
chf1
#   id  from_date    to_date    diff1
#1:  1 2015-03-09 2015-03-14  -5 days
##2:  2 2015-02-22 2015-02-24  -2 days
#3:  2 2015-05-06 2015-05-17 -11 days
#4:  3 2015-02-12 2015-02-16  -4 days
#5:  4 2015-03-10 2015-03-16  -6 days
#6:  4 2015-03-22 2015-04-07 -16 days
#7:  4 2015-06-07 2015-07-07 -30 days
#8:  4 2015-07-06 2015-07-07  -1 days
#9:  4 2015-08-02 2015-08-07  -5 days

基于OP代码中的描述,如果我们需要在按'id'分组后获取'from_date'的下一个值之间的差异,则可以使用shift的'from_date'和'to_date'进行差值计算,并将其赋值(:=)给'diff1'。
chf1[,  diff1 := difftime(shift(from_date, type = "lead"), to_date, 
                        units = "days") , by = id]
chf1
#  id  from_date    to_date   diff1
#1:  1 2015-03-09 2015-03-14 NA days
#2:  2 2015-02-22 2015-02-24 71 days
#3:  2 2015-05-06 2015-05-17 NA days
#4:  3 2015-02-12 2015-02-16 NA days
#5:  4 2015-03-10 2015-03-16  6 days
#6:  4 2015-03-22 2015-04-07 61 days
#7:  4 2015-06-07 2015-07-07 -1 days
#8:  4 2015-07-06 2015-07-07 26 days
#9:  4 2015-08-02 2015-08-07 NA days

或者它可能是
chf1[, diff1 := difftime(from_date, shift(to_date), units = "days"), by = id]

数据

chf <- structure(list(id = c(1L, 2L, 2L, 3L, 4L, 4L, 4L, 4L, 4L), 
f.date = structure(c(16503, 
16488, 16561, 16478, 16504, 16516, 16593, 16622, 16649), class = "Date"), 
t.date = structure(c(16508, 16490, 16572, 16482, 16510, 16532, 
16623, 16623, 16654), class = "Date")), .Names = c("id", 
 "f.date", "t.date"), row.names = c(NA, -9L), class = "data.frame")

 chf1 = data.table(id = chf$id,from_date = chf$f.date,to_date = chf$t.date)

嗨,我在问题中更新了代码,发现是我的错误。但是即使我再次执行了所有步骤,仍然没有得到我期望的输出。 - ssan
1
如果第三个是71,那么chf1[, diff1 := difftime(from_date, shift(to_date), units = "days"), by = id]怎么样? - akrun
1
这个完美地运作了。感谢您的回复。我认为我们也可以将此更新为答案。我能编辑答案吗? - ssan
1
@ssan 你所说的第一条记录是什么意思?也许你需要使用 chf1[, diff1 := difftime(from_date, shift(to_date, type = "lead"), units = "days"), by = id] - akrun
1
为了在@akrun的优雅解决方案中提高速度,我们可以使用data.tableIDate类。因此,代码如下:cols <- c('from_date ','to_date'); chf1[,(cols):=lapply(.SD,as.IDate),.SDcols=cols]; chf1[, diff2 := from_date-shift(to_date), by = id] - Oriol Prat
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接