Apply list of functions to list of values
W odniesieniu do to pytanie, próbowałem wymyślić najprostszy sposób, aby zastosować listę funkcji do listy wartości. Zasadniczo zagnieżdżone lapply
. Na przykład stosujemy sd
i mean
do wbudowanego zbioru danych trees
:
funs <- list(sd=sd, mean=mean)
sapply(funs, function(x) sapply(trees, x))
Aby uzyskać:
sd mean
Girth 3.138139 13.24839
Height 6.371813 76.00000
Volume 16.437846 30.17097
Ale miałem nadzieję uniknąć wewnętrznego function
i mieć coś w stylu:
sapply(funs, sapply, X=trees)
Co nie działa, ponieważ X
pasuje do pierwszego sapply
zamiast drugiego. Możemy to zrobić z functional::Curry
:
sapply(funs, Curry(sapply, X=trees))
Ale miałem nadzieję, że może jest sprytny sposób, aby to zrobić z pozycjonowaniem i dopasowaniem nazwy, którego mi brakuje.
4 answers
Ponieważ mapply
Użyj elipsy ...
, aby przekazać wektory (atomiki lub listy), a nie nazwany argument (X) jak w sapply, lapply, etc ...
nie musisz nazywać parametru X = trees
Jeśli używasz mapply zamiast sapply:
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
Byłeś o jedną literę blisko, żeby dostać to, czego szukasz ! :)
Zauważ, że użyłem listy dla funs
ponieważ nie mogę utworzyć ramki danych funkcji, dostałem błąd.
> R.version.string
[1] "R version 3.1.3 (2015-03-09)"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-10 18:15:28
Będziesz potrzebował jakiejś anonimowej funkcji, ponieważ nie ma innego sposobu na rozróżnienie nazwanych parametrów od dwóch różnych wywołań sapply
. Pokazałeś już jawną funkcję anonimową i metodę Curry
. Możesz również użyć magrittr
library(magrittr)
sapply(funs, . %>% sapply(trees, .))
# or .. funs %>% sapply(. %>% sapply(trees, .))
Ale chodzi o to, że potrzebujesz czegoś tam do podziału. "Problem" polega na tym, że sapply
wysyła do lapply
, która jest wewnętrzną funkcją , która wydaje się być zdeterminowana, aby umieścić zmiana wartości jako początek wywołania funkcji. Potrzebujesz czegoś do zmiany kolejności parametrów i ze względu na identyczne zestawy nazw parametrów nie jest możliwe, aby tease that apart bez funkcji helper dbać o disambiguation.
Funkcja mapply
pozwala przekazać listę do "MoreArgs", co pozwala ominąć konflikt nazwanych parametrów. Jest to przeznaczone do podziału między elementy, które należy wektoryzować i te, które są stałe. W ten sposób można do
mapply(sapply, funs, MoreArgs=list(X=trees))
# sd mean
# Girth 3.138139 13.24839
# Height 6.371813 76.00000
# Volume 16.437846 30.17097
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-10 15:36:42
Innym podejściem używającym purrr
byłoby:
require(purrr)
funs <- list(sd=sd, mean=mean)
trees %>% map_df(~invoke_map(funs, ,.), .id="id")
Ważne : zwróć uwagę, że pusty drugi argument invoke_map
pasuje do pozycji. Zobacz ?purrr::invoke_map
przykłady.
Co daje:
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
Zamiast nazw wierszy to podejście daje kolumnę id
zawierającą oryginalne kolumny.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-22 16:06:19
Choć nie tak budujące ani tak eleganckie jak rozwiązanie przedstawione przez @ Floo0, oto jeszcze jedno ujęcie za pomocą tidyr i 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
Ta sekwencja operacji wykonuje przyzwoitą pracę sygnalizowania intencji, kosztem dodatkowej gadatliwości.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-28 06:43:11