R Функции конвейеризации - программирование
Подтвердить что ты не робот

R Функции конвейеризации

Есть ли способ написать конвейерные функции в R, где результат одной функции сразу переходит в следующую? Я прихожу из F # и действительно оценил эту способность, но не нашел, как это сделать в R. Это должно быть просто, но я не могу найти, как это сделать. В F # он будет выглядеть примерно так:

let complexFunction x =
     x |> square 
     |> add 5 
     |> toString

В этом случае вход будет квадратным, затем добавится 5, а затем преобразуется в строку. Я хочу иметь возможность сделать что-то подобное в R, но не знаю, как это сделать. Я искал, как сделать что-то подобное, но ничего не понял. Я хочу, чтобы это импортировало данные, потому что мне обычно приходится импортировать их, а затем фильтровать. Сейчас я делаю это несколькими шагами, и мне очень хотелось бы сделать что-то в F # с помощью конвейеров.

4b9b3361

Ответ 1

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

# Define our helper functions
square <- function(x){x^2}
add5 <- function(x){x + 5}

# functional contains Compose
library(functional)

# Define our binary operator
"%|>%" <- Compose

# Create our complexFunction by 'piping' our functions
complexFunction <- square %|>% add5 %|>% as.character
complexFunction(1:5)
#[1] "6"  "9"  "14" "21" "30"


# previously had this until flodel pointed out
# that the above was sufficient
#"%|>%" <- function(fun1, fun2){ Compose(fun1, fun2) }

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

"%|>%" <- function(fun1, fun2){
    function(x){fun2(fun1(x))}
}
complexFunction <- square %|>% add5 %|>% as.character
complexFunction(1:5)
#[1] "6"  "9"  "14" "21" "30"

Ответ 2

Ниже приведен подход функционального программирования с использованием Reduce. Это на самом деле пример из ?Reduce

square <- function(x) x^2
add_5 <- function(x)  x+5
x <- 1:5
## Iterative function application:
Funcall <- function(f, ...) f(...)

Reduce(Funcall, list(as.character, add_5, square,x), right = TRUE)
## [1] "6"  "9"  "14" "21" "30"

Или даже проще использовать пакет functional и Compose

Это приятно, поскольку он создаст для вас функцию

library(functional)
do_stuff <-   Compose(square,add_5,as.character )
do_stuff(1:5)
##  [1] "6"  "9"  "14" "21" "30"

Я отмечаю, что я бы не рассматривал ни один из этих подходов идиоматически R ish (если это даже фраза)

Ответ 3

Я думаю, что вы можете просто написать функцию для выполнения желаемых шагов.

complexFunction <- function(x) {
    as.character(x^2 + 5)
}

Затем просто вызовите complexFunction(x).


Изменить, чтобы показать, что R делает внутренне (@mnel) - способ R анализирует и оценивает as.character(x^2 + 5) делает то, что вы хотите

Вы можете использовать codetools для исследования того, что R, чтобы увидеть, как передаются значения eachother

flattenAssignment(quote(as.character(x^2+5)))
[[1]]
[[1]][[1]]
x

[[1]][[2]]
`*tmp*`^2

[[1]][[3]]
`*tmp*` + 5


[[2]]
[[2]][[1]]
`as.character<-`(`*tmp*`, value = `*tmpv*`)

[[2]][[2]]
`+<-`(`*tmp*`, 5, value = `*tmpv*`)

[[2]][[3]]
`^<-`(x, 2, value = `*tmpv*`)

Или вы можете получить представление стиля Lisp, чтобы увидеть, как он анализируется (и результаты прошли)

showTree(quote(as.character(x^2+5)))
(as.character (+ (^ x 2) 5))

Ответ 4

Это работает для R довольно похоже на F #:

"%|>%" <- function(x, fun){
    if(is.function(x)) {
      function(...) fun(x(...))
    } else {
      fun(x)
    }
}

Ответ 5

Поскольку этот вопрос был задан, magrittr труба стала чрезвычайно популярной в R. Таким образом, ваш пример:

library (magrittr)

fx <- function (x) {
     x %>%
     `^` (2) %>%
     `+` (5)  %>%
     as.character ()
     }

Обратите внимание, что нотация backquote заключается в том, что я буквально использую встроенные функции R, и мне нужно специально указать их, чтобы использовать их таким образом. Более нормально названные функции (например, exp или если бы я создал вспомогательную функцию add), не нуждались бы в backquotes и выглядели бы скорее как ваш пример.

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

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