difftime with lag/lead 基于来自其他列的条件(和整洁的数据结构)

difftime with lag/lead based on condition from other column (and tidy data structure)

我从这个 post 中提取了一个函数来创建一个随机时间 efficiently generate a random sample of times and dates between two dates

这是我的数据集:

latemail <- function(N, st="2012/01/01", et="2012/12/31") {
       st <- as.POSIXct(as.Date(st))
       et <- as.POSIXct(as.Date(et))
       dt <- as.numeric(difftime(et,st,unit="sec"))
       ev <- sort(runif(N, 0, dt))
       rt <- st + ev
 }
 set.seed(42); 
 a<- print(latemail(9))  
 a<- sort(a)

data <- data.frame(time= a, place=c("Start", "B", "O", "A", "A", "Start", "A", "O", "A"), ID=c(rep(1, 5), rep(2,4)))

数据如下所示:

                  time place ID
1  2012-02-19 04:40:45 Start  1
2  2012-04-14 12:34:56     B  1
3  2012-07-08 13:16:49     O  1
4  2012-08-22 07:41:26     A  1
5  2012-08-27 21:15:08     A  1
6  2012-09-14 10:22:03 Start  2
7  2012-09-25 22:30:49     B  2
8  2012-10-30 03:43:16     B  2
9  2012-11-29 22:42:03     O  2

我想在每个组(ID)内取 "O" 和 "start" 的时差。

问题: 1)以上数据的结构是否符合tidy data?因为我认为传播数据更有意义,所以人们可以明智地采用 difftime 列。如果每个 ID 只有一行,那么它将是整齐的数据(例如,在 A 之间分隔可以称它们为 A_1、A_2,如果它们必须是列)。但是哪种格式才是整洁的数据。
2)有没有比下面更好的方法来完成这个?

  data2 <- data %>% 
  filter(place %in% c("Start", "O")) %>% 
  group_by(ID) %>% 
  mutate(diff=difftime(lead(time), time, units="days")) %>% 
  filter(!is.na(diff))

输出:

# A tibble: 2 x 4
# Groups:   ID [2]
  time                place    ID diff            
  <dttm>              <fct> <dbl> <time>          
1 2012-02-19 04:40:45 Start     1 140.31671 days  
2 2012-09-25 22:30:49 Start     2 " 65.04947 days"

我们可以保持结构不变,但通过使用 summarise 稍微简化代码(假设每个 ID 只有一个 "O" 和 "Start" .

library(dplyr)

data %>%
  group_by(ID) %>%
  summarise(diff = difftime(time[place == "O"], time[place == "Start"]))


#     ID diff            
#  <dbl> <time>          
#1     1 140.31671 days  
#2     2 " 65.04947 days"

如果有一些 ID 没有 "Start" 或 "O" 我们可以 return NA 为他们

data %>%
  group_by(ID) %>%
  summarise(diff = if (any(place == "O") & any(place == "Start"))
                   difftime(time[place == "O"], time[place == "Start"]) else NA)