#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. Это работает как шарм, очень полезно для выявления острого повреждения почек в клинических данных, спасибо!!