tabla - R: Usar valores del marco de datos A a partir de una fecha anterior a rellenar una fila en el marco de datos B
seleccionar filas en r (3)
Esto puede ser muy complicado y sospecho que requiere un conocimiento avanzado. Ahora tengo dos tipos diferentes de marcos de datos. Necesito combinar:
Los datos:
Dataframe A:
enumera todas las fechas de transfusión según el ID del paciente. Cada transfusión está representada por una fila separada, los pacientes pueden tener transfusiones múltiples. Diferentes pacientes pueden tener transfusiones en la misma fecha.
Patient ID Transfusion.Date
1 01/01/2000
1 01/30/2000
2 04/01/2003
3 04/01/2003
Los marcos de datos de Tipo B contienen resultados de pruebas en otras fechas, también por ID del paciente:
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
Lo que me gustaría tener es el Dataframe A con el mismo número de filas (1 por cada transfusión), y con el Test.Value más reciente como una columna separada. Cada fecha de transfusión debe tener el resultado de la prueba más cercana (previa) a la transfusión.
salida deseada:
->
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
Creo que la estrategia general sería subconjunto de los marcos de datos por las ID de los pacientes. Luego, tome todas las fechas de transfusión para el paciente 1, verifique cuál es el resultado más cercano a todas las fechas de prueba disponibles para cada elemento y luego devuelva el valor más cercano.
¿Cómo puedo explicarle a R que haga eso?
Edición 1 : Aquí está el código R para estos ejemplos
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''))
Editar 2:
Para aclarar, los datos resultantes deberían ser: Paciente A recibió transfusiones el Día X y el Día Y. (para df_A). Antes de la transfusión en el día X, su resultado de la prueba más reciente fue X (fecha de la prueba más cercana a la primera transfusión, en df_B). Antes de la transfusión en el día Y, su resultado de la prueba más reciente fue Y (antes de la segunda transfusión, también en df_B. Df_B también contiene un grupo de otras fechas de prueba, que no son necesarias para el resultado final.
Aquí está usando las data.table
rolling de 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
conviertedata.frame
endata.table
por referencia (sin ninguna copia adicional). Eso dará como resultadodf_A
ydf_B
ahora siendo data.tables.setkey
clasifica eldata.table
por las columnas que proporcionamos, y marca esas columnas como columnas de clave, lo que nos permite usar combinaciones basadas en búsquedas binarias .Realizamos una combinación de la forma
x[i]
en las columnas clave, donde para cada fila dei
, se devuelven las filas coincidentes dex
(si hay alguna, más NA) junto con las filas dei
. Esto es lo que llamamos un equi-join . Al agregarroll = TRUE
, en el caso de una falta de coincidencia, la última observación se traslada hacia adelante (LOCF). Esto es lo que llamamos una unión rodante . La ordenación en orden creciente (debido asetkey()
) asegura que la última observación es la fecha más reciente.
HTH
OK gracias por la ayuda de todos. Me llevó mucho trabajo, sangre, sudor y lágrimas, pero esta es la solución que se me ocurrió:
- Combina ambos marcos de datos:
df_AB <- fusionar (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>
Usando 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>
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
Editado Tenía algunos errores lógicos y algunos errores de síntesis. respondí tapply los valores enteros de las Fechas y como señaló que estaba usando el nombre de columna incorrecto en el paso de reducción de datos.