Как рассчитать среднюю разницу во времени по группам?

Мои данные выглядят так:

data <- read.table(header=T, text= '
 PID     Date           Date.diff
  1      2020-01-01     0 
  1      2020-01-02     1
  1      2020-01-10     8
  2      2020-01-15     0
  3      2020-01-02     0
  4      2020-02-02     0
  4      2020-03-01     28
  4      2020-04-15     45
  ..     ..
 ')

Каждая дата относится к дате, когда (в данном случае) пациенту был сделан тест.

Используя этот код:

data$Date.diff <- unlist(tapply(data$Date, INDEX=data$PID, FUN=function(x)
  c(0, diff(as.numeric(x)))))

Мне удалось рассчитать разницу в датах (в днях), как в столбце «Разница дат».

Если я вычислю среднее значение на основе разницы дат, результатом будет среднее количество дней между всеми тестами.

Теперь я хотел бы знать среднее количество дней между 1-м и 2-м, 2-м и 3-м тестами ect.., потому что я хочу знать, становятся ли интервалы короче/длиннее.

Это вообще возможно?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
569
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете создать столбец с номером теста для каждого пациента, а затем для каждого номера теста рассчитать среднее значение Date.diff.

library(dplyr)

data %>%
  group_by(PID) %>%
  mutate(test_number = row_number()) %>%
  group_by(test_number) %>%
  summarise(Date.diff = mean(Date.diff)) -> result
result

Спасибо за ваш ответ. Это кажется очень хорошим решением. Однако я получаю сообщение об ошибке: Ошибка в $<-.data.frame(*tmp*, Date.diff, value = list(test_number = 1:47, : замена имеет 47 строк, данные имеют 486. Есть идеи, как решить эту ошибку?

JannickLinden 15.12.2020 02:27

Я не уверен, почему вы получите эту ошибку. У меня этого не происходит для данных, которыми вы поделились. Попробуйте перезапустить R и загрузить только dplyr и запустить ответ. Есть такие функции, как summarise/mutate, которые могут быть замаскированы от plyr.

Ronak Shah 15.12.2020 02:32

Вы можете использовать отставание, чтобы создать столбец смещения в вашем фрейме данных и найти дуарацию интервала, вот решение с dplyr и lubridate:

library(dplyr)
library(lubridate)

data %>%
  mutate(across("Date", ymd)) %>%
  group_by(PID) %>%
  mutate(lag = lag(Date),
         diff2 = as.numeric(as.duration(interval(lag, Date)), "days")) %>%
  group_by(row_number()) %>%
  summarise(mean_days = mean(diff2, na.rm = TRUE), .groups = "drop")

# A tibble: 3 x 2
  `row_number()` mean_days
          <int>     <dbl>
1             1     NaN  
2             2      14.5
3             3      26.5

Использование ave лучше для группового применения функций для создания новых столбцов, то есть разницы дат в вашем случае. Он уже возвращает векторы и избегает unlisting.

dat$Date.diff <- with(dat, ave(as.numeric(Date), PID, FUN=function(x) c(0, diff(x))))

head(dat)
# PID       Date Date.diff
# 1   1 2020-01-03         0
# 2   1 2020-01-03         0
# 3   1 2020-01-18        15
# 4   1 2020-01-24         6
# 5   1 2020-01-24         0
# 6   2 2020-01-05         0

tapply теперь удобно составлять таблицы по группам. Мы можем использовать его здесь, чтобы очень легко вычислить diffзначения mean.Dates. (`1`=0 это просто косметика).

c(`1`=0, diff(with(dat, tapply(Date, PID, FUN=mean.Date))))
#   1    2    3    4    5 
# 0.0  9.0 16.2  4.4 21.6 

Данные

dat <- structure(list(PID = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L), 
    Date = structure(c(18264, 18264, 18279, 18285, 18285, 18266, 
    18281, 18286, 18291, 18298, 18287, 18295, 18303, 18308, 18310, 
    18288, 18297, 18304, 18310, 18326, 18302, 18319, 18332, 18335, 
    18345), class = "Date")), row.names = c(NA, -25L), class = "data.frame")

Другие вопросы по теме