R — Динамическая итерация для каждой группы по одному столбцу при различиях> 26,5 и отметке времени меньше < 48

#r #dplyr #iteration

#r #dplyr #итерация

Вопрос:

Я пытаюсь написать сценарий в R studio с намерением зафиксировать, развивается ли у пациента острое повреждение почек, и если да, ТО В ПЕРВЫЙ МОМЕНТ ВРЕМЕНИ, когда это произойдет. Острое повреждение почек определяется следующим образом ниже:

Увеличение креатинина (название лабораторного теста)> = 26,5 мкмоль / литр (единица измерения) в течение 48 часов

Пожалуйста, посмотрите Пример таблицы ниже, как выглядит структура данных:

 PatientKey             Creatinine            Timestamp                 Mycommentsforthisquestion
1                      70                    2020-04-03 14:10:10
1                      90                    2020-04-03 17:11:10
1                      98                    2020-04-03 19:10:10       FIRST TIME OF AKI, i.e. > 26.5 
                                                                       increase and less than 48 hours
1                      100                   2020-04-03 22:10:10       NOT RELEVANT, AKI ALREADY

2                      140                   2019-08-01 00:00:00       ONLY ONE VALUE, IGNORE SINCE NO 
                                                                       DIFFERENCE CAN BE CALCULATED

3                      120                   2017-01-06 00:00:05       CAME TO HOSPITAL WITH HIGH VALUE
3                      70                    2017-01-06 10:00:05       DECREASES MORE THAN 26.5 DONT 
                                                                       COUNT --> NO AKI                 
3                      80                    2017-01-08 10:00:05

4                      70                    2020-01-08 22:00:05
4                      60                    2020-01-09 22:00:05       NOTE IT IS NOT ALWAYS THE FIRST 
                                                                       TEST THAT SERVES AS THE COMPARISON 
                                                                       VALUE
4                      90                    2020-01-10 02:00:05       90 - 60 > 26.5 --> AKI
4                      110                   2020-01-10 06:00:05       NOT RELEVANT, AKI ALREADY 

5                      50                    2020-01-12 06:00:05
5                      70                    2020-01-13 08:00:05 
5                      80                    2020-01-14 22:00:05       NO AKI, DIFFERENCE > 26.5 BUT MORE 
                                                                       THAN 48 HOURS BETWEEN TESTS
  

Желаемый результат, который я хочу получить от этого, выглядит примерно так:

 PatientKey    CreatinineLOW    CreatinineHIGH   TimestampLOW          TimestampHIGH 
1             70               98               2020-04-03 14:10:10   2020-04-03 19:10:10
4             60               90               2020-01-09 22:00:05   2020-01-10 02:00:05
  

Пожалуйста, обратите внимание, что только у пациента 1 развилось ОПП, и, следовательно, в выходные данные должны быть включены только данные для этого пациента.

Возможно ли это сделать в R? Я попытался использовать пакет dplyr / tidyverse и сделать что-то вроде (MYDATA — это имя фрейма данных):

 datalist = list()

for (m in MYDATA$PatientKey %>% unique()) {
  x = filter(MYDATA, PatientKey == m) %>% pull(PatientKey)
  table <- MYDATA %>% filter(PatientKey == m) %>% arrange(Timestamp)
  for (i in 1:length(x)) {
     table %>% 
     mutate(indx_creat = Creatinine[1],
     new_creatinine = Creatinine - indx_creat,
     indx_time = Timestamp[i],
     new_time = as.numeric(difftime(Timestamp, indx_time, units = "hours"))) %>%
  filter(new_creatinine >= 26.5 amp; new_time <= -48) -> r
 if (nrow(r) == 0) {
   table <- table[-1,]
 } else if (nrow(r) > 0 {
   datalist[[i]] <- r
   break
  }
 }
}

summary.table = do.call(rbind, datalist)
summary.table <- summary_table %>% group_by(PatientKey) %>% slice(1)
  

Однако это не сработало! У кого-нибудь есть идеи о том, как выполнить эту работу? Для клинического сообщества было бы очень полезно использовать программирование для простого выявления острого повреждения почек!

Комментарии:

1. Как бы вы хотели определить «базовый» Cr? Минимальный Cr? Кроме того, должен ли Patientkey 4 также быть включен в выходные данные как также имеющий ОПП?

2. На самом деле с базовой частью легко справиться, поэтому только вопрос об увеличении> 26,5, который имеет важное значение, удалит другую часть из вопроса. Вы также совершенно правы в отношении пациента 4, также отредактируете это в вопросе, спасибо!

3. Было бы намного проще, если бы можно было заранее создать переменную AKI, а не пытаться создать инструмент, который будет анализировать текст, чтобы определить, является ли конкретный случай релевантным или нет.

4. Фил, я не уверен, что понимаю, о чем вы говорите, извините за это, но проблема в том, что мы априори не знаем, у каких пациентов развилось ОПП, а также какое лабораторное значение должно служить сравнительным значением (т. Е. Может быть первым, вторым, третьим, четвертым и т. Д. Значением креатинина у пациентовэто сравнение для последующих повышенных значений креатинина).

Ответ №1:

Давайте сделаем это в два этапа, чтобы сделать его более применимым в общем.

Шаг 1: найдите любое критическое увеличение для каждого наблюдения
Сначала мы создадим столбец вложенных фреймов данных, каждый из которых содержит любую строку, которая показывает критическое увеличение креатинина:

 library(dplyr)
library(purrr)
library(tidyr)
library(lubridate)

# loading OPs data
df <- structure(list(PatientKey = c(1L, 1L, 1L, 1L, 2L, 3L, 3L, 3L, 
4L, 4L, 4L, 4L, 5L, 5L, 5L), Creatinine = c(70L, 90L, 98L, 100L, 
140L, 120L, 70L, 80L, 70L, 60L, 90L, 110L, 50L, 70L, 80L), Timestamp = c("2020-04-03 14:10:10", 
"2020-04-03 17:11:10", "2020-04-03 19:10:10", "2020-04-03 22:10:10", 
"2019-08-01 00:00:00", "2017-01-06 00:00:05", "2017-01-06 10:00:05", 
"2017-01-08 10:00:05", "2020-01-08 22:00:05", "2020-01-09 22:00:05", 
"2020-01-10 02:00:05", "2020-01-10 06:00:05", "2020-01-12 06:00:05", 
"2020-01-13 08:00:05", "2020-01-14 22:00:05")), row.names = c(NA, 
-15L), class = "data.frame")

# find any critical increase, per observation row
df2 <- df %>%
  mutate(
    Timestamp = as_datetime(Timestamp)
  ) %>%
  group_by(PatientKey) %>%
  do(
    mutate(.,
      critical_increase = map2(
        Creatinine, Timestamp,
        .f = function(c, t, data) {
          data %>%
            filter(
              Creatinine - c >= 26.5,
              Timestamp > t,
              as.numeric(Timestamp - t, units = "hours") <= 48
            ) %>%
            select(Timestamp, Creatinine)
        },
        data = .
      )
    )
  ) %>%
  ungroup()
  

Приведенный выше код отображает «Креатинин» и «Временные метки» каждой строки и добавляет сгруппированное подмножество данных соответствующего пациента, чтобы отфильтровать его на предмет критического увеличения. Этот отфильтрованный df сохраняется в столбце «critical_increase».

Шаг 2: приведите данные в ожидаемый формат
Теперь, чтобы получить описанный вами формат, мы отключим фреймы данных, которые мы рассчитали ранее, переименуем столбцы в те, которые вы хотите, чтобы они были, и выберите первую строку для каждого пациента с помощью «TimestampHIGH»:

 # unnest, rename amp; select first critical increase
df_final <- df2 %>%
  unnest(critical_increase, names_sep = ".") %>%
  transmute(
    PatientKey = PatientKey,
    CreatinineLOW = Creatinine,
    CreatinineHIGH = critical_increase.Creatinine,
    TimestampLOW = Timestamp,
    TimestampHIGH = critical_increase.Timestamp
  ) %>%
  group_by(PatientKey) %>%
  arrange(TimestampHIGH, desc(TimestampLOW)) %>%
  filter(row_number() == 1) %>%
  ungroup()
  

Вы могли бы легко вносить изменения, например arrange(desc(CreatinineHIGH - CreatinineLOW)) , находить максимальное наблюдаемое увеличение в течение 48 часов.

Результат
Приведенное выше дает ожидаемый результат:

 > df_final
# A tibble: 2 x 5
  PatientKey CreatinineLOW CreatinineHIGH TimestampLOW        TimestampHIGH      
       <int>         <int>          <int> <dttm>              <dttm>             
1          4            60             90 2020-01-09 22:00:05 2020-01-10 02:00:05
2          1            70             98 2020-04-03 14:10:10 2020-04-03 19:10:10
  

Комментарии:

1. Это работает как шарм, очень полезно для выявления острого повреждения почек в клинических данных, спасибо!!