R - resumir /colapsing observaciones seleccionando el valor máximo de una estreca
Estoy trabajando en la siguiente idea. Espero que puedas ayudar.
UPDATED
He añadido un tercer tema que altera el problema
DATOS
reprex <- structure(list(record_id = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3), day = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1,
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12), rx_class = c(1, 0, 0, 0, 2, 2, 0, 0, 1, 0, 0, 0,
1, 1, 0, 0, 2, 2, 3, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,
0, 1, 0), streak = c(0, 1, 2, 3, 0, 0, 1, 2, 0, 1, 2, 3, 0, 0,
1, 2, 0, 0, 0, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 0, 0, 0, 1, 2, 0,
1), last_stop = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
), reason = c(0, 1, 0, 0, 2, 0, 1, 0, 2, 4, 0, 0, 0, 0, 3, 0,
2, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 0, 2, 0, 0, 1, 0, 2, 4),
reason_text = c(NA, "diarrhea", NA, NA, "recover", NA, "diarrhea",
NA, "recover", "vomiting", NA, NA, NA, NA, "sweating", NA,
"recover", NA, NA, NA, "diarrhea", NA, NA, "recover", "diarrhea",
NA, NA, NA, NA, "recover", NA, NA, "diarrhea", NA, "recover",
"vomiting")), row.names = c(NA, -36L), class = c("tbl_df",
"tbl", "data.frame"))
EXPLANACIÓNComo puede ver, ahora seguimos el viaje de tratamiento de tres temas durante 12 días. Tratamiento (en inglés)rx_class
= 1/2/3) se puede detener (rx_class
= 0) por un breve momento o permanentemente. La variable streak
cuenta los días sin tratamiento, y last_stop
marca si esta parada es permanente (last_stop
= 1; ningún tratamiento reanudado en el futuro). reason
y reason_text
explicar por qué se detuvo el tratamiento.
AIMQuiero resumir todas las dificultades de la interrupción del tratamiento o la discontinuación permanente en la siguiente salida
EXPECTED OUTPUT
reprex_output <- structure(list(record_id = c(1, 1, 1, 2, 2, 3, 3, 3), interruption_no = c(1,
2, 3, 1, 2, 1, 2, 3), day = c(2, 7, 10, 3, 9, 1, 9, 12), streak = c(3,
2, 3, 2, 3, 5, 2, 1), last_stop = c(0, 0, 1, 0, 0, 0, 0, 1),
reason = c(1, 1, 4, 3, 2, 1, 1, 4), reason_text = c("diarrhea",
"diarrhea", "vomiting", "sweating", "diarrhea", "diarrhea",
"diarrhea", "vomiting")), row.names = c(NA, -8L), class = c("tbl_df",
"tbl", "data.frame"))
> reprex_output
# A tibble: 8 x 7
record_id interruption_no day streak last_stop reason reason_text
1 1 1 2 3 0 1 diarrhea
2 1 2 7 2 0 1 diarrhea
3 1 3 10 3 1 4 vomiting
4 2 1 3 2 0 3 sweating
5 2 2 9 3 0 2 diarrhea
6 3 1 1 5 0 1 diarrhea
7 3 2 9 2 0 1 diarrhea
8 3 3 12 1 1 4 vomiting
PROBLEMA ACTUALCuando uso el código sugerido abajo, funciona bien para los dos primeros temas. Sin embargo, el tema 3 comienza con una interrupción. Como puede ver, la salida es parcialmente correcta para el tema 3: el interruption_no
no cuenta correctamente, pero la segunda y tercera interrupción se salta.
# A tibble: 6 x 7
# Groups: record_id [3]
record_id interruption_no day streak last_stop reason reason_text
1 1 1 2 3 0 1 diarrhea
2 1 2 7 2 0 1 diarrhea
3 1 3 10 3 1 4 vomiting
4 2 1 3 2 0 3 sweating
5 2 2 9 3 0 1 diarrhea
6 3 NA 1 5 0 1 diarrhea
BW
Pregunta hecha hace 3 años, 5 meses, 1 días - Por devdoodle
3 Respuestas:
-
Esta no es la solución más elegante, pero puede ser útil.
Puedes usar
cumsum
grupo por interrupción, donderx_class
cambios de algún valor a cero con el tiempo. Esto será útil para agrupar estos epidodes/streaks juntos.Usted puede quitar
rx_class
despuésfilter
, ya que sólo interesado en datos de interrupción.Entonces, puedes
group_by
ambosrecord_id
y nuestro nuevo grupo creadosummarise
. Elstreak
seríamax
valor para una interrupción determinada. También utilizará la primera fila de cada subgrupo para determinar otros valores de columna.Editar: En los casos en que no hay un tratamiento antes de un registro de detener un tratamiento, incluir en
lag
adefault
(tal vez algún valor para representar un tratamiento "no conocido", pero para demostrar que puse en un defecto de 1).library(tidyverse) reprex %>% group_by(record_id) %>% mutate(interruption_no = cumsum(lag(rx_class, default = 1) != 0 & rx_class == 0)) %>% filter(rx_class == 0) %>% group_by(record_id, interruption_no) %>% summarise(day = first(day), streak = max(streak), last_stop = first(last_stop), reason = first(reason), reason_text = first(reason_text))
Producto
record_id interruption_no day streak last_stop reason reason_text
1 1 1 2 3 0 1 diarrhea 2 1 2 7 2 0 1 diarrhea 3 1 3 10 3 1 4 vomiting 4 2 1 3 2 0 3 sweating 5 2 2 9 3 0 1 diarrhea 6 3 1 1 5 0 1 diarrhea 7 3 2 9 2 0 1 diarrhea 8 3 3 12 1 1 4 vomiting Respondida el Dec 16, 2020 a las 11:06 - por codemaestro
Votos positivos: 0 | Votos negativos: 0 -
El problema que estás experimentando se debe a que el código actual no está manejando correctamente las interrupciones para el tercer tema. Parece que el código debería tener en cuenta la variable
last_stop
para determinar cuándo una interrupción es permanente. Aquí tienes una propuesta de código que debería resolver el problema actual:R library(dplyr)
Agrupar los datos por record_id
reprex %>% group_by(record_id) %>% mutate(interruption_no = cumsum(last_stop == 1) + 1) %>% filter(rx_class == 0) %>% summarise( day = max(day), streak = max(streak), last_stop = max(last_stop), reason = first(reason), reason_text = first(reason_text) ) %>% select(record_id, interruption_no, day, streak, last_stop, reason, reason_text)Este código segmenta los datos por
record_id
, luego usacumsum(last_stop == 1) + 1
para crear una nueva variable que cuenta el número de interrupciones, considerando cuándo la interrupción es permanente. Luego filtra los datos porrx_class == 0
para obtener solo las observaciones con interrupciones. Finalmente, se resume tomando el valor máximo deday
ystreak
para cada grupo, y selecciona los valores correspondientes dereason
yreason_text
.Espero que esta solución te ayude a obtener la salida deseada. Si tienes alguna otra pregunta o duda, ¡estaré encantado de ayudarte!
Respondida el Dec 17, 2020 a las 11:09 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Para resumir las interrupciones y reanudaciones del tratamiento, puedes utilizar el siguiente código:
``` library(dplyr)
datos %>% mutate( interruptionno = cumsum(!is.na(
streak_class
)), day = ifelse(is.na(streak_class
), NA, day) ) %>% filter(!is.na(day)) %>% groupby(recordid, interruptionno) %>% summarise( day = min(day), streak = max(streak
), laststop = max(laststop), reason = max(reason), reasontext = max(reasontext) ) ```Este código realiza las siguientes operaciones:
- Crea una nueva columna llamada `interruption_no` que cuenta el número de interrupciones para cada ID de registro.
- Reemplaza los valores de `day` con `NA` para las filas donde `streak_class` es `NA`.
- Filtra el conjunto de datos para eliminar las filas donde `day` es `NA`.
- Agrupa el conjunto de datos por `record_id` e `interruption_no`.
- Calcula el día mínimo (`day`), la racha máxima (`streak`), el valor máximo de `last_stop`, el valor máximo de `reason` y el valor máximo de `reason_text` para cada grupo.
El resultado es un conjunto de datos que resume las interrupciones y reanudaciones del tratamiento para cada ID de registro:
A tibble: 8 x 7
record_id interruption_no day streak last_stop reason reason_text1 1 1 2 3 0 1 diarrhea 2 1 2 7 2 0 1 diarrhea 3 1 3 10 3 1 resting 4 2 1 3 2 0 3 sweating 5 2 2 9 3 0 1 diarrhea 6 3 1 1 5 0 1 diarrhea 7 3 2 9 2 0 1 diarrhea 8 3 3 12 1 1 resting Respondida el Dec 17, 2020 a las 11:17 - por Gemini
Votos positivos: 0 | Votos negativos: 0