Подтвердить что ты не робот

Применить список функций к списку значений

Что касается этого вопроса, я пытался выяснить простейший способ применения списка функций к списку значений, В принципе, вложенный lapply. Например, здесь мы применяем sd и mean к встроенному набору данных trees:

funs <- list(sd=sd, mean=mean)
sapply(funs, function(x) sapply(trees, x))

чтобы получить:

              sd     mean
Girth   3.138139 13.24839
Height  6.371813 76.00000
Volume 16.437846 30.17097

Но я надеялся избежать внутреннего function и иметь что-то вроде:

sapply(funs, sapply, X=trees)

который не работает, потому что X совпадает с первым sapply вместо второго. Мы можем сделать это с помощью functional::Curry:

sapply(funs, Curry(sapply, X=trees))

но я надеялся, что, возможно, был умный способ сделать это с помощью позиционного и имени, которое мне не хватает.

4b9b3361

Ответ 1

Так как mapply используйте ellipsis ... для передачи векторов (атомы или списки), а не именованного аргумента (X), как в sapply, lapply, etc ..., вам не нужно указывать параметр X = trees, если вы используете mapply вместо 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

У вас было одно письмо, чтобы получить то, что вы искали!:)

Обратите внимание, что я использовал список для funs, потому что я не могу создать фрейм данных функций, я получил ошибку.

> R.version.string
[1] "R version 3.1.3 (2015-03-09)"

Ответ 2

В основном вам понадобится анонимная функция, потому что не будет другого способа различать именованные параметры для двух разных вызовов sapply. Вы уже указали явную анонимную функцию и метод Curry. Вы также можете использовать magrittr

 library(magrittr)
 sapply(funs, . %>%  sapply(trees, .))
 # or .. funs %>% sapply(. %>%  sapply(trees, .))

но дело в том, что вам нужно что-то сделать для разделения. "Проблема" заключается в том, что sapply отправляет lapply, которая является внутренней функцией , которая, как представляется, помещает изменяющиеся значения в начало вызова функции. Вам нужно что-то изменить параметры, и из-за идентичных наборов имен параметров невозможно дразнить это отдельно, без вспомогательной функции, чтобы заботиться об устранении неоднозначности.

Функция mapply позволяет вам передавать список в "MoreArgs", который позволяет обойти конфликт с именованным параметром. Это предназначено для разделения между элементами, которые вы должны векторизовать, и теми, которые исправлены. Таким образом, вы можете сделать

mapply(sapply, funs, MoreArgs=list(X=trees))
#               sd     mean
# Girth   3.138139 13.24839
# Height  6.371813 76.00000
# Volume 16.437846 30.17097

Ответ 3

Другим подходом, использующим purrr, будет:

require(purrr)

funs <- list(sd=sd, mean=mean)
trees %>% map_df(~invoke_map(funs, ,.), .id="id")

Важно. Обратите внимание на пустой второй аргумент invoke_map для соответствия по позиции. См. Примеры ?purrr::invoke_map.

который дает вам:

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

Вместо названий ростов этот подход дает вам столбец id, содержащий исходные столбцы.

Ответ 4

Хотя это не так наглядно и не столь изящно, как решение, представленное @Floo0, вот еще одно взятие с использованием tidyr и 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

Эта последовательность операций делает достойную работу по намерениям сигнализации за счет дополнительной многословности.