usar sheet instalar functions como cheat r dplyr

sheet - ¿Se resume dplyr cuando el retorno de la función es vectorial?



select in r (2)

Es por eso que todavía amo a plyr::ddply() :

library(plyr) f <- function(z) setNames(coef(lm(x ~ y, z)), c("a", "b")) ddply(df, ~ group, f) # group a b # 1 A 0.5213133 0.04624656 # 2 B 0.3020656 0.01450137 # 3 C 0.2189537 0.22998823

La función dplyr::summarize() puede aplicar funciones arbitrarias sobre los datos, pero parece que la función debe devolver un valor escalar. Tengo curiosidad por saber si hay una manera razonable de manejar las funciones que devuelven un valor vectorial sin hacer varias llamadas a la función.

Aquí hay un ejemplo mínimo un tanto tonto. Considere una función que da múltiples valores, tales como:

f <- function(x,y){ coef(lm(x ~ y, data.frame(x=x,y=y))) }

y datos que se parecen a:

df <- data.frame(group=c(''A'',''A'',''A'',''A'',''B'',''B'',''B'',''B'',''C'',''C'',''C'',''C''), x=rnorm(12,1,1), y=rnorm(12,1,1))

Me gustaría hacer algo como:

df %>% group_by(group) %>% summarise(f(x,y))

y recupere una tabla que tiene 2 columnas agregadas para cada uno de los valores devueltos en lugar de la columna 1 habitual. En su lugar, este error con: Expecting single value

Por supuesto, podemos obtener múltiples valores de dlpyr::summarise() dando el argumento de la función varias veces:

f1 <- function(x,y) coef(lm(x ~ y, data.frame(x=x,y=y)))[[1]] f2 <- function(x,y) coef(lm(x ~ y, data.frame(x=x,y=y)))[[2]] df %>% group_by(group) %>% summarise(a = f1(x,y), b = f2(x,y))

Esto da la salida deseada:

group a b 1 A 1.7957245 -0.339992915 2 B 0.5283379 -0.004325209 3 C 1.0797647 -0.074393457

pero la codificación de esta manera es ridículamente cruda y fea.

data.table maneja este caso más sucintamente:

dt <- as.data.table(df) dt[, f(x,y), by="group"]

pero crea una salida que extiende la tabla usando filas adicionales en lugar de columnas adicionales, lo que resulta en una salida que es confusa y más difícil de trabajar con:

group V1 1: A 1.795724536 2: A -0.339992915 3: B 0.528337890 4: B -0.004325209 5: C 1.079764710 6: C -0.074393457

Por supuesto, hay estrategias de apply más clásicas que podríamos usar aquí,

sapply(levels(df$group), function(x) coef(lm(x~y, df[df$group == x, ]))) A B C (Intercept) 1.7957245 0.528337890 1.07976471 y -0.3399929 -0.004325209 -0.07439346

pero esto sacrifica tanto la elegancia como la sospecha de la velocidad de la agrupación. En particular, tenga en cuenta que no podemos usar nuestra función predefinida f en este caso, pero tenemos que codificar la agrupación en la definición de la función.

¿Existe una función dplyr para manejar este caso? Si no es así, ¿existe una manera más elegante de manejar este proceso de evaluación de funciones de valores vectoriales sobre un cuadro de datos por grupo?


Podrías intentar do

library(dplyr) df %>% group_by(group) %>% do(setNames(data.frame(t(f(.$x, .$y))), letters[1:2])) # group a b #1 A 0.8983217 -0.04108092 #2 B 0.8945354 0.44905220 #3 C 1.2244023 -1.00715248

La salida basada en f1 y f2 es

df %>% group_by(group) %>% summarise(a = f1(x,y), b = f2(x,y)) # group a b #1 A 0.8983217 -0.04108092 #2 B 0.8945354 0.44905220 #3 C 1.2244023 -1.00715248

Actualizar

Si está utilizando data.table , la opción para obtener un resultado similar es

library(data.table) setnames(setDT(df)[, as.list(f(x,y)) , group], 2:3, c(''a'', ''b''))[]