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)
我从这个 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)