tablas mutate funcion filtrar datos data comando casos agrupar r dplyr

funcion - dplyr:: mutate para agregar mĂșltiples valores



funcion select en r (5)

Hay un par de problemas sobre esto en el repositorio de Dplyr Github , y al menos una pregunta de SO relacionada, pero ninguna de ellas cubre mi pregunta, creo.

Aquí está mi caso de uso: quiero calcular los intervalos de confianza binomiales exactos

dd <- data.frame(x=c(3,4),n=c(10,11)) get_binCI <- function(x,n) { rbind(setNames(c(binom.test(x,n)$conf.int),c("lwr","upr"))) } with(dd[1,],get_binCI(x,n)) ## lwr upr ## [1,] 0.06673951 0.6524529

Puedo hacer esto con do() pero me pregunto si hay una manera más expresiva de hacerlo (se siente como que mutate() podría tener un argumento .n como se está discutiendo para el resumen () ...)

library("dplyr") dd %>% group_by(x,n) %>% do(cbind(.,get_binCI(.$x,.$n))) ## Source: local data frame [2 x 4] ## Groups: x, n ## ## x n lwr upr ## 1 3 10 0.06673951 0.6524529 ## 2 4 11 0.10926344 0.6920953


Aquí hay algunas posibilidades con rowwise y nesting .

library("dplyr") library("tidyr")

Marco de datos con repetidas combinaciones x / n, por diversión

dd <- data.frame(x=c(3, 4, 3), n=c(10, 11, 10))

una versión de la función CI que devuelve un marco de datos, como @ Joran''s

get_binCI_df <- function(x,n) { binom.test(x, n)$conf.int %>% setNames(c("lwr", "upr")) %>% as.list() %>% as.data.frame() }

Agrupando por x y n como antes, elimina el duplicado.

dd %>% group_by(x,n) %>% do(get_binCI_df(.$x,.$n)) # # A tibble: 2 x 4 # # Groups: x, n [2] # x n lwr upr # <dbl> <dbl> <dbl> <dbl> # 1 3 10 0.1181172 0.8818828 # 2 4 11 0.1092634 0.6920953

El uso de rowwise mantiene todas las filas pero elimina x y n menos que las vuelva a cbind(. usando cbind(. (Como Ben lo hace en su OP).

dd %>% rowwise() %>% do(cbind(., get_binCI_df(.$x,.$n))) # Source: local data frame [3 x 4] # Groups: <by row> # # # A tibble: 3 x 4 # x n lwr upr # * <dbl> <dbl> <dbl> <dbl> # 1 3 10 0.06673951 0.6524529 # 2 4 11 0.10926344 0.6920953 # 3 3 10 0.06673951 0.6524529

Parece que la anidación podría funcionar de manera más limpia, pero esto es lo mejor que puedo conseguir. Usar mutate significa que puedo usar x y n directamente en lugar de .$x y .$n , pero mutar espera un solo valor, por lo que debe incluirse en la list .

dd %>% rowwise() %>% mutate(ci=list(get_binCI_df(x, n))) %>% unnest() # # A tibble: 3 x 4 # x n lwr upr # <dbl> <dbl> <dbl> <dbl> # 1 3 10 0.06673951 0.6524529 # 2 4 11 0.10926344 0.6920953 # 3 3 10 0.06673951 0.6524529

Finalmente, parece que algo como esto es un problema abierto (a partir del 5 de octubre de 2017) para dplyr; vea https://github.com/tidyverse/dplyr/issues/2326 ; Si se implementa algo así, ¡esa será la forma más fácil!


Aquí hay una solución rápida utilizando el paquete data.table lugar

Primero, un pequeño cambio en la función.

get_binCI <- function(x,n) as.list(setNames(binom.test(x,n)$conf.int, c("lwr", "upr")))

Entonces, simplemente

library(data.table) setDT(dd)[, get_binCI(x, n), by = .(x, n)] # x n lwr upr # 1: 3 10 0.06673951 0.6524529 # 2: 4 11 0.10926344 0.6920953


Esto utiliza un flujo de trabajo dplyr "estándar", pero como @BenBolker observa en los comentarios, requiere llamar a get_binCI dos veces:

dd %>% group_by(x,n) %>% mutate(lwr=get_binCI(x,n)[1], upr=get_binCI(x,n)[2]) x n lwr upr 1 3 10 0.06673951 0.6524529 2 4 11 0.10926344 0.6920953


Otra opción podría ser usar la familia de funciones purrr::map .

Si reemplaza rbind con dplyr::bind_rows en la función get_binCI :

library(tidyverse) dd <- data.frame(x = c(3, 4), n = c(10, 11)) get_binCI <- function(x, n) { bind_rows(setNames(c(binom.test(x, n)$conf.int), c("lwr", "upr"))) }

Puedes usar purrr::map2 con tidyr::unnest :

dd %>% mutate(result = map2(x, n, get_binCI)) %>% unnest() #> x n lwr upr #> 1 3 10 0.06673951 0.6524529 #> 2 4 11 0.10926344 0.6920953

O purrr::map2_dfr con dplyr::bind_cols :

dd %>% bind_cols(map2_dfr(.$x, .$n, get_binCI)) #> x n lwr upr #> 1 3 10 0.06673951 0.6524529 #> 2 4 11 0.10926344 0.6920953


Otra variante, aunque creo que todos estamos dividiendo los pelos aquí.

> dd <- data.frame(x=c(3,4),n=c(10,11)) > get_binCI <- function(x,n) { + as_data_frame(setNames(as.list(binom.test(x,n)$conf.int),c("lwr","upr"))) + } > > dd %>% + group_by(x,n) %>% + do(get_binCI(.$x,.$n)) Source: local data frame [2 x 4] Groups: x, n x n lwr upr 1 3 10 0.06673951 0.6524529 2 4 11 0.10926344 0.6920953

Personalmente, si solo vamos por legibilidad, encuentro esto preferible:

foo <- function(x,n){ bi <- binom.test(x,n)$conf.int data_frame(lwr = bi[1], upr = bi[2]) } dd %>% group_by(x,n) %>% do(foo(.$x,.$n))

... pero ahora estamos realmente dividiendo los pelos.