`emmeans` for a gls model does not run inside `map`
Esta pregunta se inspira en no puede utilizar emmeans dentro del mapa, y relacionados con Mapa `joint_tests` a una lista después de encajar un modelo 'gls' y `group_by` y mantener los niveles de agrupación como el nombre del marco de datos anidado
Quiero envolver varias pruebas en un flujo de trabajo.
Esto funciona para un glm
modelo.
library(dplyr)
library(purrr)
library(emmeans)
library(nlme)
diamond_result <- diamonds %>%
group_by(cut) %>%
nest() %>%
ungroup %>%
dplyr::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$jt
$Ideal
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
$Premium
model term df1 df2 F.ratio p.value
x 1 Inf 2074.371 <.0001
Pero la misma sintaxis no funciona para una gls
modelo así que me detuve emmeans()
Paso. Eventualmente, quiero joint_tests
, emmeans
, y contrast
en el mutate
paso.
diamonds_emm2 <- diamonds %>%
group_by(cut) %>%
nest() %>%
ungroup() %>%
dplyr::mutate(models=map(data,~gls(price ~ x + y + z + clarity,
weights = varIdent(form = ~ 1|color),
data =.x)),
means=map(models,~emmeans::emmeans(.x,"clarity",data=.x$data)),
across(models:p_cont, setNames, .$cut))
Error: Problem with `mutate()` input `means`.
x undefined columns selected
ℹ Input `means` is `map(models, ~emmeans::emmeans(.x, "clarity", data = .x$data))`.
Run `rlang::last_error()` to see where the error occurred.
Problem with `mutate()` input `means`.
x undefined columns selected
ℹ Input `means` is `map(models, ~emmeans::emmeans(.x, "clarity", data = .x$data))`.
Backtrace:
1. `%>%`(...)
18. base::.handleSimpleError(...)
19. dplyr:::h(simpleError(msg, call))
Problem with `mutate()` input `means`.
x undefined columns selected
ℹ Input `means` is `map(models, ~emmeans::emmeans(.x, "clarity", data = .x$data))`.
Backtrace:
█
1. ├─`%>%`(...)
2. ├─dplyr::mutate(...)
3. ├─dplyr:::mutate.data.frame(...)
4. │ └─dplyr:::mutate_cols(.data, ...)
5. │ ├─base::withCallingHandlers(...)
6. │ └─mask$eval_all_mutate(dots[[i]])
7. ├─purrr::map(models, ~emmeans::emmeans(.x, "clarity", data = .x$data))
8. │ └─.f(.x[[i]], ...)
9. │ └─emmeans::emmeans(.x, "clarity", data = .x$data)
10. │ ├─base::do.call(ref_grid, args)
11. │ └─(function (object, at, cov.reduce = mean, cov.keep = get_emm_option("cov.keep"), ...
12. │ ├─emmeans::recover_data(object, data = as.data.frame(data), ...)
13. │ └─emmeans:::recover_data.gls(...)
14. │ └─emmeans:::recover_data.call(...)
15. │ ├─tbl[, vars, drop = FALSE]
16. │ └─base::`[.data.frame`(tbl, , vars, drop = FALSE)
17. │ └─base::stop("undefined columns selected")
18. └─base::.handleSimpleError(...)
19. └─dplyr:::h(simpleError(msg, call))
El código funciona bien en este paso.
diamonds_emm <- diamonds %>%
group_by(cut) %>% nest() %>%
mutate(models=map(data,~gls(price ~ x + y + z + clarity,
weights = varIdent(form = ~ 1|color),
data =.x)))
¿Cómo trabajo alrededor de este problema? Gracias.
Actualización: map2
función de la respuesta de Ronak solucionó el problema en el means
pasos pero no hará contrastes pares. ¿Qué me perdí?
diamonds %>%
group_by(cut) %>%
nest() %>%
mutate(models=map(data,~gls(price ~ x + y + z + clarity,
weights = varIdent(form = ~ 1|color),
data =.x)),
means = map2(data, models,~emmeans::emmeans(.y,"clarity",data=.x)),
p_cont = map2(means, ~emmeans::contrast(.y, "pairwise",infer = c(T,T)))) %>%
ungroup %>%
mutate(across(models:p_cont, setNames, .$cut)) -> result
Error: Problem with `mutate()` input `p_cont`.
x object '.z' not found
ℹ Input `p_cont` is `map(means, ~emmeans::contrast(.y, "pairwise", infer = c(T, T)))`.
ℹ The error occurred in group 1: cut = "Fair".
Dar un nuevo nombre a la entrada en el p_cont
paso, como ~emmeans::contrast(.z, "pairwise", infer = c(T, T)))
No solucionó el problema.
Pregunta hecha hace 3 años, 4 meses, 29 días - Por codecraftsman
4 Respuestas:
-
Datos de pase así como modelo en el
emmeans
paso utilizandomap2
. Paracontrasts
yjoint_tests
puedes usarmap
.library(tidyverse) library(emmeans) library(nlme) diamonds %>% group_by(cut) %>% nest() %>% mutate(models=map(data,~gls(price ~ x + y + z + clarity, weights = varIdent(form = ~ 1|color), data =.x))) %>% ungroup %>% mutate(means = map2(data, models,~emmeans(.y,"clarity",data=.x)), p_cont = map(means, contrast, "pairwise"), joint_tests = map(means, joint_tests), across(models:joint_tests, setNames, .$cut)) -> result result # cut data models means p_cont joint_tests #
#1 Ideal Respondida el Dec 17, 2020 a las 19:28 - por scriptsorcererf493
Votos positivos: 0 | Votos negativos: 0 -
Si no insistes en usar el
purrr::map
familia, sugeriría usar el nuevo (dplyr 1.0.0)rowwise
estilo. Es menos confuso, ya que puede utilizar los nombres de variable/columna como es y no hay necesidad de elegir el correctomap
función y averiguar la notación de la lambda. Sólo tienes que envolver la llamada de la funciónlist(...)
. Sólo la última llamadaacross
necesita ser llamado a los no agrupadosdata.frame
.library(tidyverse) library(emmeans) library(nlme) diamonds_emm_row <- diamonds %>% nest_by(cut) %>% dplyr::mutate(models = list(gls(price ~ x + y + z + clarity, weights = varIdent(form = ~ 1|color), data = data)), jt = list(joint_tests(models, data = data)), means = list(emmeans::emmeans(models, "clarity", data = data)), p_cont = list(emmeans::contrast(means, "pairwise", infer = c(T,T)))) %>% ungroup %>% mutate(across(models:p_cont, setNames, .$cut)) diamonds_emm_row #> # A tibble: 5 x 6 #> cut data models jt means p_cont #>
#> 1 Fair [1,610 × 9] #> 2 Good [4,906 × 9] #> 3 Very Go… [12,082 × 9] #> 4 Premium [13,791 × 9] #> 5 Ideal [21,551 × 9] Creado el 2021-01-01 por el paquete de reprex (v0.3.0)
Esto produce más o menos el mismo resultado que el uso
purrr::map
. "Más o menos", porqueidentical()
no lo mostrará, ya que la llamada de función se guarda en los atributos (y otros lugares), y difiere dependiendo de si utiliza {dplyr}'srowwise
estilo omap
notación de lambda.diamonds_emm_map <- diamonds %>% nest_by(cut) %>% ungroup() %>% dplyr::mutate(models=map(data,~gls(price ~ x + y + z + clarity, weights = varIdent(form = ~ 1|color), data =.x)), jt = map2(models, data, ~ joint_tests(.x, data = .y)), means = map2(data, models, ~ emmeans::emmeans(.y, "clarity", data = .x)), p_cont = map(means, ~emmeans::contrast(.x, "pairwise", infer = c(T,T))), across(models:p_cont, setNames, .$cut)) map2(diamonds_emm_row, diamonds_emm_map, all.equal, check.attributes = FALSE) #> $cut #> [1] TRUE #> #> $data #> [1] TRUE #> #> $models #> [1] "Component \"Fair\": Component \"call\": target, current do not match when deparsed" #> [2] "Component \"Good\": Component \"call\": target, current do not match when deparsed" #> [3] "Component \"Very Good\": Component \"call\": target, current do not match when deparsed" #> [4] "Component \"Premium\": Component \"call\": target, current do not match when deparsed" #> [5] "Component \"Ideal\": Component \"call\": target, current do not match when deparsed" #> #> $jt #> [1] TRUE #> #> $means #> [1] TRUE #> #> $p_cont #> [1] TRUE
Creado el 2021-01-01 por el paquete de reprex (v0.3.0)
Respondida el Dec 17, 2020 a las 19:37 - por bytebarde61c
Votos positivos: 0 | Votos negativos: 0 -
El problema que estás experimentando con
emmeans
dentro demap
cuando usas un modelogls
se debe a que las funcionesemmeans
no están tratando adecuadamente los datos debido a la estructura de los objetos generados por el modelogls
.Para solucionar este problema y permitir que las funciones
emmeans
funcionen correctamente con modelosgls
dentro de unmap
, puedes hacer lo siguiente:- Para el cálculo de las medias (means), puedes usar `map2` en lugar de `map`. Esta función te permite aplicar una función a dos listas diferentes al mismo tiempo. En este caso, puedes combinar los datos y los modelos para asegurarte de que las medias se calculen correctamente:
R diamonds_emm2 <- diamonds %>% group_by(cut) %>% nest() %>% ungroup() %>% dplyr::mutate(models=map(data,~gls(price ~ x + y + z + clarity, weights = varIdent(form = ~ 1|color), data =.x)), means=map2(data, models, ~emmeans::emmeans(.y, "clarity", data = .x$data)), across(models:means, setNames, .$cut))
- Para el cálculo de los contrastes (p_cont), también debes utilizar `map2` de manera similar para asegurarte de que los contrastes se calculen correctamente:
R diamonds_emm2 <- diamonds_emm2 %>% mutate(p_cont = map2(data, means, ~emmeans::contrast(.y, "pairwise", infer = c(TRUE, TRUE))), across(models:p_cont, setNames, .$cut))
Al utilizar
map2
en lugar demap
para las funcionesemmeans
ycontrast
, puedes garantizar que se apliquen correctamente a los datos y modelos dentro de un flujo de trabajo en R. Espero que esta solución te ayude a resolver el problema que estás experimentando.Respondida el Dec 18, 2020 a las 19:30 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Problema con emmeans() para un modelo gls dentro de map()
El problema surge porque
emmeans()
espera un objeto de modelolm
oglm
como entrada, mientras quegls()
produce un objeto de clasegls
.Solución:
Para
emmeans()
: Utiliza la funciónrecover_data()
para convertir el objetogls
en un marco de datos antes de aplicaremmeans()
.means = map2(data, models, ~emmeans::emmeans(.y, "clarity", data = emmeans::recover_data(.x)))
Para
contrast()
:Opción 1: Utiliza
emmeans() %>% contrast()
para realizar contrastes directamente en los resultados deemmeans()
.p_cont = map(means, ~.x %>% emmeans::contrast("pairwise", infer = c(T, T)))
Opción 2: Utiliza la función
lsmeans()
del paquetelsmeans
para realizar contrastes en objetosgls
.library(lsmeans) p_cont = map(means, ~lsmeans(.x, "clarity") %>% contrast(pairs = TRUE, adjust = "tukey"))
Ejemplo completo:
library(dplyr) library(purrr) library(emmeans) library(nlme) library(lsmeans) diamond_result <- diamonds %>% group_by(cut) %>% nest() %>% ungroup %>% dplyr::mutate( models=map(data,~gls(price ~ x + y + z + clarity, weights = varIdent(form = ~ 1|color), data =.x)), means = map2(data, models,~emmeans::emmeans(.y,"clarity",data=emmeans::recover_data(.x))), p_cont = map(means,~lsmeans(.x, "clarity") %>% contrast(pairs = TRUE, adjust = "tukey")), across(models:p_cont, setNames, .$cut) )
Nota: Si utilizas la opción 2 para los contrastes, necesitarás instalar y cargar el paquete
lsmeans
antes de ejecutar el código.Respondida el Dec 18, 2020 a las 19:34 - por Gemini
Votos positivos: 0 | Votos negativos: 0