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, donde rx_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és filter, ya que sólo interesado en datos de interrupción.

    Entonces, puedes group_by ambos record_id y nuestro nuevo grupo creado summarise. El streak sería max 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 a default (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 usa cumsum(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 por rx_class == 0 para obtener solo las observaciones con interrupciones. Finalmente, se resume tomando el valor máximo de day y streak para cada grupo, y selecciona los valores correspondientes de reason y reason_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_text 1 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