计算每个id的后续数据

时间:2018-04-05 21:47:38

标签: r dplyr data.table lubridate

我试图重新计算中等规模数据框(16000行100个变量)的跟进时间。

这里已经部分问了这个问题 Calculating time difference by ID 但这里所描述的实质上是我想要做的事情,但我没有时间只有日期可用。

我想弄清楚为什么它只适用于日期。

当我运行此代码时,它可以工作:

生成数据:

Incident.ID.. = c(rep("INCFI0000029582",4), rep("INCFI0000029587",4))
date = c("2014-09-25 08:39:45", "2014-09-25 08:39:48", "2014-09-25 08:40:44", "2014-10-10 23:04:00", "2014-09-25 08:33:32", "2014-09-25 08:34:41", "2014-09-25 08:35:24", "2014-10-10 23:04:00")
df = data.frame(Incident.ID..,date, stringsAsFactors = FALSE)

运行代码

library(dplyr)
library(lubridate)
df %>%
  group_by(Incident.ID..) %>%
  mutate(diff = c(0, diff(ymd_hms(date))))

输出

  Incident.ID..   date                    diff
  <chr>           <chr>                  <dbl>
1 INCFI0000029582 2014-09-25 08:39:45       0.
2 INCFI0000029582 2014-09-25 08:39:48       3.
3 INCFI0000029582 2014-09-25 08:40:44      56.
4 INCFI0000029582 2014-10-10 23:04:00 1347796.
5 INCFI0000029587 2014-09-25 08:33:32       0.
6 INCFI0000029587 2014-09-25 08:34:41      69.
7 INCFI0000029587 2014-09-25 08:35:24      43.
8 INCFI0000029587 2014-10-10 23:04:00 1348116.

我的数据采用YMD格式,因此这似乎是合乎逻辑的:

生成数据

Incident.ID.. = c(rep("INCFI0000029582",4), rep("INCFI0000029587",4))
date = c("2014-09-20", "2014-09-21", "2014-09-22", "2014-09-23", "2014-09-26", "2014-09-27", "2014-09-28", "2014-10-10")
df = data.frame(Incident.ID..,date, stringsAsFactors = FALSE)

运行代码

library(dplyr)
library(lubridate)
df %>%
  group_by(Incident.ID..) %>%
  mutate(diff = c(0, diff(ymd(date))))

输出

  Incident.ID..   date        diff
  <chr>           <chr>      <dbl>
1 INCFI0000029582 2014-09-20    0.
2 INCFI0000029582 2014-09-21    1.
3 INCFI0000029582 2014-09-22    1.
4 INCFI0000029582 2014-09-23    1.
5 INCFI0000029587 2014-09-26    0.
6 INCFI0000029587 2014-09-27    1.
7 INCFI0000029587 2014-09-28    1.
8 INCFI0000029587 2014-10-10   12.

它现在给出了后续观察之间的差异,而不是第一个Incident.ID ..

这里给出了一个答案:Date difference per ID with dplyr without hours, minutes or seconds但我仍然不明白为什么使用上面这个非常相似的代码它不起作用。 (任何为什么它现在给出天数而不是几秒钟的差异)。

使用数据表方法时,我得到相同的结果:

padded.diff = function(x) c(0L, diff(x)) 
library(data.table) 
setDT(df)[, date.diff := padded.diff(as.POSIXct(date)), by = Incident.ID..]
View(df)

对此行为的任何解释都将非常受欢迎,因为它不会给出解析错误。 (它可能与posix时间有关,但我感到困惑)

2 个答案:

答案 0 :(得分:0)

我想象一下diff函数调用不同的方法,具体取决于你传递给它的类。

c("2014-09-20") %>% ymd() %>% class()
#    [1] "Date"

c("2014-09-25 08:39:45") %>% ymd_hms() %>% class()
#    [1] "POSIXct" "POSIXt" 

因此,将类Date的对象传递给diff将为您提供日期(通过调用diff.Date),而传递类POSIXt的对象将提供你有秒(diff.POSIXt)。

答案 1 :(得分:0)

我不确定,但我不会说它与课程有关。 我的建议就是这个。

Incident.ID.. = c(rep("INCFI0000029582",4), rep("INCFI0000029587",5)) 
#changing second rep from 4 to 5
date = c("2014-09-20", "2014-09-21", "2014-09-22", "2014-09-23", "2014-09-26", "2014-09-27", "2014-09-28", "2014-10-10", "2014-10-10 00:00:01") 
#adding one more timeframe right after the last one
df = data.frame(Incident.ID..,date, stringsAsFactors = FALSE)

padded.diff = function(x) c(0L, diff(x)) 
df2=within(df, {
date.diff   = ave(as.numeric(as.POSIXct(date)), Incident.ID.., FUN = padded.diff) })
df2 = df2[-nrow(df2),]

df2
Incident.ID..       date date.diff
1 INCFI0000029582 2014-09-20         0
2 INCFI0000029582 2014-09-21     86400
3 INCFI0000029582 2014-09-22     86400
4 INCFI0000029582 2014-09-23     86400
5 INCFI0000029587 2014-09-26         0
6 INCFI0000029587 2014-09-27     86400
7 INCFI0000029587 2014-09-28     86400
8 INCFI0000029587 2014-10-10   1036800

我的猜测是显示天而不是秒是某种形式的截断。所以我添加一个元素,更改为1秒,以便在几秒钟内强制显示。

或只使用1天的知识,包含86400秒。