У меня есть этот набор данных
library(dplyr)
# creating a dataframe
data_frame <- data.frame(id = c(1,1,2,2,3,3),
col2 = c("start", "finish", "start", "finish","start", "finish"),
col3 = c(as.POSIXct("2021-05-08 08:32:07"),
as.POSIXct("2021-05-08 08:32:45"),
as.POSIXct("2020-11-28 23:32:09"),
as.POSIXct("2020-11-28 23:32:25"),
as.POSIXct("2021-05-08 08:32:07"),
as.POSIXct("2021-05-08 08:32:12")))
# computing difference from start to finish
df <- data_frame %>%
arrange(id) %>%
mutate(timetaken = col3 - lag(col3))
df
Я хочу
Чтобы рассчитать разницу во времени, я могу рассчитать задержку, как показано выше. Однако я хочу получить результат следующим образом и вычислить среднее время этой переменной.
> df
id col2 col3 timetaken
1 1 start 2021-05-08 08:32:07 NA secs
2 1 finish 2021-05-08 08:32:45 38 secs
3 2 start 2020-11-28 23:32:09 NA secs
4 2 finish 2020-11-28 23:32:25 16 secs
5 3 start 2021-05-08 08:32:07 NA secs
6 3 finish 2021-05-08 08:32:12 5 secs
Есть идеи, как этого добиться?
Вы можете вычислить разницу между «началом» и «финишем» для каждой группы следующим образом:
data_frame %>%
mutate(timetaken = ifelse(col2 == "start", NA,
col3[col2 == "finish"] - col3[col2 == "start"]),
.by = id)
# id col2 col3 timetaken
# 1 1 start 2021-05-08 08:32:07 NA
# 2 1 finish 2021-05-08 08:32:45 38
# 3 2 start 2020-11-28 23:32:09 NA
# 4 2 finish 2020-11-28 23:32:25 16
# 5 3 start 2021-05-08 08:32:07 NA
# 6 3 finish 2021-05-08 08:32:12 5
Получите среднюю разницу во времени следующим образом:
mean(data_frame$timetaken, na.rm = TRUE)
#[1] 19.66667
Если вы хотите использовать dplyr::lag()
:
library(dplyr)
df <- data_frame |>
mutate(timetaken = col3 - lag(col3), .by = id)
df
# id col2 col3 timetaken
# 1 1 start 2021-05-08 08:32:07 NA secs
# 2 1 finish 2021-05-08 08:32:45 38 secs
# 3 2 start 2020-11-28 23:32:09 NA secs
# 4 2 finish 2020-11-28 23:32:25 16 secs
# 5 3 start 2021-05-08 08:32:07 NA secs
# 6 3 finish 2021-05-08 08:32:12 5 secs
и подход dplyr()
для получения среднего значения (хотя, как и в предыдущем ответе, я считаю, что в этом случае используется очиститель базы R):
summarise(df, mean(timetaken, na.rm = TRUE))
# mean(timetaken, na.rm = TRUE)
# 1 19.66667 secs
Если вам нужна только одна строка для каждого идентификатора, вы можете изменить форму:
tidyr::pivot_wider(data_frame, names_from=col2, values_from=col3) |>
mutate(timetaken=difftime(finish, start)) |>
print() |>
summarise(avg=mean(timetaken, na.rm=TRUE))
# A tibble: 3 x 4
id start finish timetaken
<dbl> <dttm> <dttm> <drtn>
1 1 2021-05-08 08:32:07 2021-05-08 08:32:45 38 secs
2 2 2020-11-28 23:32:09 2020-11-28 23:32:25 16 secs
3 3 2021-05-08 08:32:07 2021-05-08 08:32:12 5 secs
# A tibble: 1 x 1
avg
<drtn>
1 19.66667 secs
Предполагая, что это всегда начало/окончание каждой строки, тогда мы можем получить разницу для каждой строки и подмножества чередующихся результатов:
diffSec <- diff(data_frame$col3)[ c(TRUE, FALSE) ]
diffSec
# Time differences in secs
# [1] 38 16 5
mean(diffSec)
# Time difference of 19.66667 secs
Мне кажется, что для желаемой операции данные должны быть в широком формате. Если ваши реальные данные организованы так же хорошо, как и игрушечные, нам не нужно учитывать группировку по id
, см. ave()
.
База R
reshape(data_frame, direction = "wide", idvar = "id", timevar = "col2") |>
setNames(c("id", "start", "finish")) |> # cosmetics
transform(diff = difftime(finish, start))
предоставление
id start finish diff
1 1 2021-05-08 08:32:07 2021-05-08 08:32:45 38 secs
3 2 2020-11-28 23:32:09 2020-11-28 23:32:25 16 secs
5 3 2021-05-08 08:32:07 2021-05-08 08:32:12 5 secs
@Эдвард Ааа, извини. Не видел. Свел мой ответ только к базе.
Чем ваш ответ отличается от моего?