R: Использование значений из кадра данных A с даты, предшествующей заполнению строки в кадре данных B
Это может быть очень сложно, и я подозреваю, что это требует передовых знаний. У меня есть два разных типа данных. Я должен комбинировать:
Данные:
Dataframe A:
перечислены все даты переливания по идентификатору пациента. Каждое переливание представлено отдельной строкой, пациенты могут иметь множественные переливания. В тот же день у разных пациентов могут быть переливания.
Patient ID Transfusion.Date
1 01/01/2000
1 01/30/2000
2 04/01/2003
3 04/01/2003
Кадры данных типа B содержат результаты тестов в другие даты, а также идентификатор пациента:
Patient ID Test.Date Test.Value
1 11/30/1999 negative
1 01/15/2000 700 copies/uL
1 01/27/2000 900 copies/uL
2 03/30/2003 negative
Я хотел бы иметь Dataframe A с таким же количеством строк (1 для каждой переливания) и с самым последним Test.Value в качестве отдельного столбца. Каждая дата трансфузии должна иметь результат теста теста, проведенного наиболее близко (ранее) до переливания.
желаемый результат:
- >
Patient ID Transfusion.Date Pre.Transfusion.Test
1 01/01/2000 negative
1 01/30/2000 900 copies/ul
2 04/01/2003 negative
3 04/01/2003 NA
Я думаю, что общая стратегия заключалась бы в подмножестве data.frames по идентификаторам пациентов. Затем возьмите все даты переливания для пациента 1, проверьте, какой результат ближе всего к всем доступным значениям test_dates для каждого элемента, а затем верните ближайшее значение.
Как я могу объяснить R для этого?
Изменить 1. Здесь приведен код R для этих примеров.
df_A <- data.frame(MRN = c(1,1,2,3),
Transfusion.Date = as.Date(c('01/01/2000', '01/30/2000',
'04/01/2003','04/01/2003'),'%m/%d/%Y'))
df_B <- data.frame(MRN = c(1,1,1,2),
Test.Date = as.Date(c('11/30/1999', '01/15/2000', '01/27/2000',
'03/30/2003'),'%m/%d/%Y'), Test.Result = c('negative',
'700 copies/ul','900 copies/ul','negative'))
Изменить 2:
Чтобы уточнить, результирующие данные должны быть: пациент А получил переливание в день X и день Y. (для df_A). До переливания в день X его последний результат теста был Х (ближайшая дата теста для первого переливания в df_B). До переливания в день Y его последний результат теста был Y (до второго переливания, также в df_B. Df_B также содержит кучу других дат тестирования, которые не нужны для конечного результата.
Ответы
Ответ 1
Здесь с использованием data.table
катящихся соединений:
require(data.table)
setkey(setDT(df_A), MRN, Transfusion.Date)
setkey(setDT(df_B), MRN, Test.Date)
df_B[df_A, roll=TRUE]
# MRN Test.Date Test.Result
# 1: 1 2000-01-01 negative
# 2: 1 2000-01-30 900 copies/ul
# 3: 2 2003-04-01 negative
# 4: 3 2003-04-01 NA
-
setDT
преобразует data.frame
в data.table
по ссылке (без какого-либо дополнительного копирования). Это приведет к тому, что df_A
и df_B
теперь будут data.tables.
-
setkey
сортирует data.table
по столбцам, которые мы предоставили, и маркирует эти столбцы в качестве ключевых столбцов, что позволяет нам использовать объединения на основе бинарного поиска.
-
Мы выполняем объединение формы x[i]
в ключевых столбцах, где для каждой строки i
сопоставляемые строки x
(если есть, еще NA) вместе с i
строками возвращаются. Это то, что мы называем equi-join. Добавляя roll = TRUE
, в случае несоответствия последнее наблюдение переносится вперед (LOCF). Это то, что мы называем скользящим соединением. Сортировка в порядке возрастания (из-за setkey()
) гарантирует, что последнее наблюдение является самой последней датой.
НТН
Ответ 2
dfLast <- df_B[ df_B$Test.Date %in%
as.Date( tapply(df_B$Test.Date, df_B$MRN, tail,1),"1970-01-01"), ]
merge(df_A, dfLast, by=c(1:2,1:2) ,all.y=TRUE)
MRN Transfusion.Date Test.Result
1 1 2000-01-27 900 copies/ul
2 2 2003-03-30 negative
Под ред. Были некоторые логические ошибки и некоторые ситактивные ошибки. tapply вернули целые значения дат и, как вы указали, я использовал неправильное имя столбца на шаге сокращения данных.
Ответ 3
ОК спасибо за помощь. Мне потребовалось много труда, крови, потом и слез, но это решение, с которым я столкнулся:
- Объединить оба фрейма данных:
df_AB <-merge (df_A, df_B, all.x = T)
df_AB:
MRN Transfusion.Date Test.Date Test.Result
1 1 2000-01-01 1999-11-30 negative
2 1 2000-01-01 2000-01-15 700 copies/ul
3 1 2000-01-01 2000-01-27 900 copies/ul
4 1 2000-01-30 1999-11-30 negative
5 1 2000-01-30 2000-01-15 700 copies/ul
6 1 2000-01-30 2000-01-27 900 copies/ul
7 2 2003-04-01 2003-03-30 negative
8 3 2003-04-01 <NA> <NA>
Используя dplyr
df_tests <- df_AB %>%
group_by(MRN, Transfusion.Date) %>%
mutate(Time.Difference = Transfusion.Date - Test.Date) %>%
filter(Time.Difference > 0) %>%
arrange(Time.Difference) %>%
summarize(Test.Date = Test.Date[1], Test.Result = Test.Result[1])
df_tests:
MRN Transfusion.Date Test.Date Test.Result
1 1 2000-01-01 1999-11-30 negative
2 1 2000-01-30 1999-11-30 negative
3 2 2003-04-01 2003-03-30 negative
using merge again for MRN3:
df_desired <- merge(df_A, df_tests, all.x = T)
MRN Transfusion.Date Test.Date Test.Result
1 1 2000-01-01 1999-11-30 negative
2 1 2000-01-30 2000-01-27 900 copies/ul
3 2 2003-04-01 2003-03-30 negative
4 3 2003-04-01 <NA> <NA>