tablas - Aplicar lista de funciones a lista de valores.
tablas en r (4)
Aunque no es tan edificante ni tan elegante como la solución presentada por @ Floo0, aquí hay otra tidyr usa tidyr y dplyr :
library(dplyr)
library(tidyr)
fns <- funs(sd = sd, mean = mean)
trees %>%
gather(property, value, everything()) %>%
group_by(property) %>%
summarise_all(fns)
# A tibble: 3 x 3
# property sd mean
# <chr> <dbl> <dbl>
# 1 Girth 3.138139 13.24839
# 2 Height 6.371813 76.00000
# 3 Volume 16.437846 30.17097
Esta secuencia de operaciones hace un trabajo decente de intención de señalización, a costa de verbosidad adicional.
En referencia a esta pregunta , intentaba descubrir la forma más sencilla de aplicar una lista de funciones a una lista de valores. Básicamente, un lapply
anidado. Por ejemplo, aquí aplicamos sd
y mean
a los trees
conjuntos de datos integrados:
funs <- list(sd=sd, mean=mean)
sapply(funs, function(x) sapply(trees, x))
Llegar:
sd mean
Girth 3.138139 13.24839
Height 6.371813 76.00000
Volume 16.437846 30.17097
Pero esperaba evitar la function
interna y tener algo como:
sapply(funs, sapply, X=trees)
que no funciona porque X
coincide con la primera sapply
lugar de la segunda. Podemos hacerlo con functional::Curry
:
sapply(funs, Curry(sapply, X=trees))
pero esperaba que tal vez hubiera una forma inteligente de hacer esto con la coincidencia de posición y nombre que me faltan.
Básicamente, va a necesitar una función anónima de algún tipo, porque no habría otra manera de distinguir los parámetros nombrados de las dos llamadas diferentes de sapply
. Ya has mostrado una función anónima explícita y el método de Curry
. También magrittr
usar magrittr
library(magrittr)
sapply(funs, . %>% sapply(trees, .))
# or .. funs %>% sapply(. %>% sapply(trees, .))
Pero el punto es que necesitas algo para hacer la división. El "problema" es que la sapply
envía a la lapply
que es una función interna que parece determinada a colocar los valores cambiantes como el comienzo de la llamada a la función. Necesita algo para reordenar los parámetros y, debido a los conjuntos idénticos de nombres de parámetros, no es posible separar eso sin una función auxiliar para encargarse de la desambiguación.
La función mapply
le permite pasar una lista a "MoreArgs", que permite una forma de evitar el conflicto de parámetros con nombre. El objetivo es dividir entre los elementos que debe vectorizar y los que están arreglados. Asi puedes hacer
mapply(sapply, funs, MoreArgs=list(X=trees))
# sd mean
# Girth 3.138139 13.24839
# Height 6.371813 76.00000
# Volume 16.437846 30.17097
Dado que mapply
usa puntos suspensivos ...
para pasar vectores (atómicos o listas) y no un argumento con nombre (X) como en sapply, lapply, etc ...
no necesita nombrar el parámetro X = trees
si usa mapply en su lugar de la aplicación:
funs <- list(sd = sd, mean = mean)
x <- sapply(funs, function(x) sapply(trees, x))
y <- sapply(funs, mapply, trees)
> y
sd mean
Girth 3.138139 13.24839
Height 6.371813 76.00000
Volume 16.437846 30.17097
> identical(x, y)
[1] TRUE
¡Estabas cerca de una carta para obtener lo que estabas buscando! :)
Tenga en cuenta que usé una lista para funs
porque no puedo crear un marco de datos de funciones, recibí un error.
> R.version.string
[1] "R version 3.1.3 (2015-03-09)"
Otro enfoque utilizando purrr
sería:
require(purrr)
funs <- list(sd=sd, mean=mean)
trees %>% map_df(~invoke_map(funs, ,.), .id="id")
Importante : invoke_map
en cuenta el segundo argumento vacío de invoke_map
para que coincida con la posición. Vea los ejemplos de ?purrr::invoke_map
.
lo que te da:
Source: local data frame [3 x 3]
id sd mean
<chr> <dbl> <dbl>
1 Girth 3.138139 13.24839
2 Height 6.371813 76.00000
3 Volume 16.437846 30.17097
En lugar de rownames, este enfoque le proporciona una id
columna que contiene las columnas originales.