`group_by` y mantener los niveles de agrupación como el nombre del marco de datos anidado

Esta pregunta está relacionada e inspirada en no puede utilizar emmeans dentro del mapa

Estoy haciendo varios pasos de análisis de datos con el siguiente código. Quiero mantener los niveles de mi factor de agrupación como los nombres de los marcos de datos anidados y utilizar esos nombres para identificar cada uno de los pasos a lo largo del camino, en lugar de usar la enumeración predeterminada [[1]], [[2], [[3]], etc. No entiendo el error que tengo. Por favor, vea cómo puedo arreglar mi código.

library(dplyr)
library(purrr)
library(emmeans)
data("warpbreaks")
wb_emm <-  warpbreaks %>%
  group_by(tension) %>% 
  setNames(unique(.x$tension)) %>%
  nest() %>%
  mutate(models=map(data,~glm(breaks~wool,data=.x))) %>%
  mutate(jt = map(models, ~emmeans::joint_tests(.x, data = .x$data))) %>%
  mutate(means=map(models,~emmeans::emmeans(.x,"wool",data=.x$data))) %>%
  mutate(p_cont = map(means, ~emmeans::contrast(.x, "pairwise",infer = c(T,T))))

Error in unique(.x$tension) : object '.x' not found

Originalmente lo hice. group_by(tension) %>% setNames(unique(tension)) y se fue Error in unique(tension) : object 'tension' not foundTambién lo intenté split(.$tension) pero está en conflicto con nest()

Pero... tension los niveles son legibles.

 unique(warpbreaks$tension)
[1] L M H
Levels: L M H

El código funciona bien sin el setNames(unique(.x$tension)) %>% paso.

wb_emm$p_cont
[[1]]
 contrast estimate   SE  df asymp.LCL asymp.UCL z.ratio p.value
 A - B        16.3 6.87 Inf      2.87      29.8 2.378   0.0174 

Confidence level used: 0.95 

[[2]]
 contrast estimate   SE  df asymp.LCL asymp.UCL z.ratio p.value
 A - B       -4.78 4.27 Inf     -13.1      3.59 -1.119  0.2630 

Confidence level used: 0.95 

[[3]]
 contrast estimate   SE  df asymp.LCL asymp.UCL z.ratio p.value
 A - B        5.78 3.79 Inf     -1.66      13.2 1.523   0.1277 

Confidence level used: 0.95 

Gracias.

Actualización: desde la segunda solución proporcionada por Ronak Shah abajo, intenté diamonds pero los nombres no cambiaron. El código funciona con ungroup()%>% o ungroup%>%.

diamonds %>%
  group_by(cut) %>%
  nest() %>% 
  ungroup %>%
  mutate(models=map(data,~glm(price ~ x + y + z + clarity + color,data=.x)),
         jt = map(models, ~emmeans::joint_tests(.x, data = .x$data)),
         means=map(models,~emmeans::emmeans(.x,"color",data=.x$data)),
         p_cont = map(means, ~emmeans::contrast(.x, "pairwise",infer = c(T,T))),
         across(models:p_cont, stats::setNames,  .$cut)) -> diamond_result
> diamond_result$jt
[[1]]
 model term df1 df2 F.ratio p.value
 x            1 Inf 611.626 <.0001 
 y            1 Inf   2.914 0.0878 
 z            1 Inf 100.457 <.0001 
 clarity      7 Inf 800.852 <.0001 
 color        6 Inf 256.796 <.0001 

Pregunta hecha hace 3 años, 5 meses, 0 días - Por codecraftsman


3 Respuestas:

  • Necesitas añadir setNames en el map paso :

    library(tidyverse)
    
    warpbreaks %>%
      group_by(tension) %>% 
      nest() %>%
      ungroup %>%
      mutate(models=map(data,~glm(breaks~wool,data=.x)),
            jt = map(models, ~emmeans::joint_tests(.x, data = .x$data)),
            means=map(models,~emmeans::emmeans(.x,"wool",data=.x$data)),
            p_cont = setNames(map(means, 
                      ~emmeans::contrast(.x, "pairwise",infer = c(T,T))),.$tension))
    

    Si desea nombrar todo el uso de salida de la lista across :

    warpbreaks %>%
      group_by(tension) %>% 
      nest() %>%
      ungroup %>%
      mutate(models=map(data,~glm(breaks~wool,data=.x)),
             jt = map(models, ~emmeans::joint_tests(.x, data = .x$data)),
             means=map(models,~emmeans::emmeans(.x,"wool",data=.x$data)),
             p_cont = map(means, ~emmeans::contrast(.x, "pairwise",infer = c(T,T))),
             across(models:p_cont, setNames,  .$tension)) -> result
    
    result$jt
    
    #$L
    # model term df1 df2 F.ratio p.value
    # wool         1 Inf   5.653 0.0174 
    
    
    #$M
    # model term df1 df2 F.ratio p.value
    # wool         1 Inf   1.253 0.2630 
    
    
    #$H
    # model term df1 df2 F.ratio p.value
    # wool         1 Inf   2.321 0.1277 
    

    Respondida el Dec 17, 2020 a las 03:50 - por scriptwarrior

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás teniendo en tu código se debe a una confusión en el uso de la función setNames y la referencia a la variable .x. Aquí te muestro cómo corregirlo:

    En lugar de setNames(unique(.x$tension)), deberías usar mutate(name = unique(tension)) para crear una nueva columna con los nombres de los niveles de la variable tension en cada grupo. Luego, puedes usar esa columna como el nombre del marco de datos anidado.

    Aquí está el código corregido:

    r
    library(dplyr)
    library(purrr)
    library(emmeans)
    data("warpbreaks")
    wb_emm <-  warpbreaks %>%
      group_by(tension) %>% 
      mutate(name=unique(tension)) %>%
      nest() %>%
      mutate(models=map(data, ~glm(breaks~wool, data=.x))) %>%
      mutate(jt = map(models, ~emmeans::joint_tests(.x, data = .x$data))) %>%
      mutate(means=map(models, ~emmeans::emmeans(.x, "wool", data=.x$data))) %>%
      mutate(p_cont = map(means, ~emmeans::contrast(.x, "pairwise", infer = c(TRUE, TRUE))))
    

    Con esta corrección, ahora deberías poder mantener los nombres de los marcos de datos anidados como los niveles de la variable tension y utilizarlos en cada paso del análisis de datos.

    Espero que esta solución te haya sido útil. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 18, 2020 a las 03:49 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás recibiendo se debe a que estás intentando acceder a una columna que no existe dentro del marco de datos anidado. Específicamente, estás intentando acceder a la columna tension dentro del marco de datos anidado, pero esta columna no existe.

    Para solucionar este error, puedes utilizar la función pull() para extraer la columna tension del marco de datos anidado antes de intentar utilizarla para establecer los nombres de los marcos de datos anidados. Aquí tienes el código corregido:

    
    wb_emm <-  warpbreaks %>%
      group_by(tension) %>% 
      setNames(unique(pull(tension))) %>%
      nest() %>%
      mutate(models=map(data,~glm(breaks~wool,data=.x))) %>%
      mutate(jt = map(models, ~emmeans::joint_tests(.x, data = .x$data))) %>%
      mutate(means=map(models,~emmeans::emmeans(.x,"wool",data=.x$data))) %>%
      mutate(p_cont = map(means, ~emmeans::contrast(.x, "pairwise",infer = c(T,T))))
    

    Ahora, el código debería funcionar sin errores y los nombres de los marcos de datos anidados se establecerán según los niveles del factor de agrupación tension.

    Además, para mantener los niveles de agrupación como nombres de marcos de datos anidados, puedes utilizar la función across() junto con setNames(). Aquí tienes un ejemplo:

    
    diamonds %>%
      group_by(cut) %>%
      nest() %>%
      ungroup %>%
      mutate(across(models:p_cont, stats::setNames,  .$cut)) -> diamond_result
    

    En este código, la función across() se utiliza para aplicar la función setNames() a las columnas models, jt, means y p_cont. La función setNames() establece los nombres de estas columnas según los niveles del factor de agrupación cut. El resultado final es un conjunto de marcos de datos anidados con nombres que reflejan los niveles del factor de agrupación.

    Respondida el Dec 18, 2020 a las 03:59 - por Gemini

    Votos positivos: 0 | Votos negativos: 0