Primero un poco de contexto: estoy trabajando con un conjunto de datos que incluye datos relacionados con la salud. Incluye puntajes de cuestionarios antes y después del tratamiento. Sin embargo, algunos clientes reaparecen dentro de los datos para un tratamiento adicional. He proporcionado un ejemplo simulado de los datos en la sección de código.

He intentado encontrar una solución en dplyr, ya que este es el paquete con el que estoy más familiarizado, pero no logré lo que quería.

#Example/mock data
   ClientNumber<-c("4355", "2231", "8894", "9002", "4355", "2231", "8894", "9002", "4355", "2231")
        Pre_Post<-c(1,1,1,1,2,2,2,2,1,1)
        QuestionnaireScore<-c(62,76,88,56,22,30, 35,40,70,71)
        df<-data.frame(ClientNumber, Pre_Post, QuestionnaireScore)
        df$ClientNumber<-as.character(df$ClientNumber)
        df$Pre_Post<-as.factor(df$Pre_Post)
        View(df)
#tried solution
df2<-df%>%
  group_by(ClientNumber)%>%
  filter( Pre_Post==1|Pre_Post==2)
#this doesn't work, or needs more code to it

Como puede ver, los primeros cuatro números de clientes tienen un puntaje previo y posterior al tratamiento. Esto es bueno. Sin embargo, los números de cliente 4355 y 2231 aparecen nuevamente al final (se podría decir que han recaído y han comenzado un nuevo tratamiento). Estos dos clientes no tienen una puntuación posterior al tratamiento.

Solo quiero analizar a los clientes que tienen un puntaje previo y posterior, por lo tanto, necesito filtrar a los clientes que han completado el tratamiento, excluyendo aquellos que no tienen un puntaje posterior al tratamiento si han aparecido nuevamente en los datos. En relación con el ejemplo que he proporcionado, quiero incluir los primeros 8 para el análisis, excluyendo los dos últimos, ya que no tienen una puntuación posterior al tratamiento.

0
Robin Turkington 10 may. 2019 a las 14:18

3 respuestas

La mejor respuesta

Otra opción es crear grupos de 2 por cada ClientNumber y seleccionar solo aquellos grupos que tengan 2 filas.

library(dplyr)

df %>%
  arrange(ClientNumber) %>%
  group_by(ClientNumber, group = cumsum(Pre_Post == 1)) %>%
  filter(n() == 2) %>%
  ungroup() %>%
  select(-group)

#  ClientNumber Pre_Post QuestionnaireScore
#    <chr>        <fct>          <dbl>
#1    2231         1               76
#2    2231         2               30
#3    4355         1               62
#4    4355         2               22
#5    8894         1               88
#6    8894         2               35
#7    9002         1               56
#8    9002         2               40

Lo mismo se puede traducir en la base R usando ave

new_df <- df[order(df$ClientNumber), ]
subset(new_df, ave(Pre_Post,ClientNumber,cumsum(Pre_Post == 1),FUN = length) == 2)
0
Ronak Shah 10 may. 2019 a las 11:57

Si estos casos deben mantenerse en orden, podría intentar:

library(dplyr)

df %>%
  group_by(ClientNumber) %>%
  filter(!duplicated(Pre_Post) & n_distinct(Pre_Post) == 2)

  ClientNumber Pre_Post QuestionnaireScore
  <fct>           <dbl>              <dbl>
1 4355                1                 62
2 2231                1                 76
3 8894                1                 88
4 9002                1                 56
5 4355                2                 22
6 2231                2                 30
7 8894                2                 35
8 9002                2                 40

No sé si realmente necesitas usar n_distinct() pero no te hará daño mantenerlo. Esto eliminará los casos que tengan una calificación previa pero no una calificación posterior si existen en los datos.

1
H 1 10 may. 2019 a las 11:35

Primero arrange ClientNumbers luego group_by y finalmente filtrar usando dplyr::lead y dplyr::lag

library(dplyr)
df %>% arrange(ClientNumber) %>% group_by(ClientNumber) %>% 
       filter(Pre_Post==1 & lead(Pre_Post)==2 | Pre_Post==2 & lag(Pre_Post)==1)

# A tibble: 8 x 3
# Groups:   ClientNumber [4]
   ClientNumber Pre_Post QuestionnaireScore
   <fct>           <dbl>              <dbl>
1 2231                1                 76
2 2231                2                 30
3 4355                1                 62
4 4355                2                 22
5 8894                1                 88
6 8894                2                 35
7 9002                1                 56
8 9002                2                 40
1
A. Suliman 10 may. 2019 a las 11:43