difftime с запаздыванием / опережением на основе условий из другого столбца (и аккуратной структуры данных)
Я взял функцию из этого поста, чтобы создать случайное время, чтобы эффективно генерировать случайную выборку времени и дат между двумя датами.
Вот мой набор данных:
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
Я хотел бы взять разницу во времени, когда место "O" и "начало", в каждой группе (ID).
Вопросы:
1) Соответствует ли структура приведенных выше данных приведенным данным? Потому что я думаю, что имеет больше смысла распространять данные, чтобы можно было использовать столбцы difftime. Если у каждого идентификатора есть только одна строка, это будут аккуратные данные (например, для разделения между ними можно назвать их 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"
1 ответ
Мы можем сохранить структуру как есть, но немного упростить код, используя summarise
(при условии, что у вас есть только одно "O" и "Start" для каждого ID
,
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
мы не можем вернуть ни "Старт", ни "О" NA
для них
data %>%
group_by(ID) %>%
summarise(diff = if (any(place == "O") & any(place == "Start"))
difftime(time[place == "O"], time[place == "Start"]) else NA)