2012-11-13 43 views
14

Có cách nào để viết các hàm pipelined trong R trong đó kết quả của một hàm chuyển ngay lập tức sang hàm tiếp theo không? Tôi đến từ F # và thực sự đánh giá cao khả năng này nhưng đã không tìm thấy làm thế nào để làm điều đó trong R. Nó phải được đơn giản nhưng tôi không thể tìm thấy như thế nào. Trong F #, nó sẽ trông giống như sau:R Chức năng đường ống

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

Trong trường hợp này đầu vào sẽ được bình phương, sau đó thêm 5 vào và sau đó chuyển thành chuỗi. Tôi muốn có thể làm một cái gì đó tương tự trong R nhưng không biết làm thế nào. Tôi đã tìm kiếm cách để làm một cái gì đó như thế này nhưng đã không đi qua bất cứ điều gì. Tôi muốn điều này để nhập dữ liệu vì tôi thường phải nhập dữ liệu và sau đó lọc. Ngay bây giờ tôi làm điều này trong nhiều bước và thực sự muốn có thể làm một cái gì đó theo cách bạn sẽ làm trong F # với đường ống.

+1

Tôi không hoàn toàn rõ ràng về những gì bạn đang yêu cầu: 'complexFunction <- function (x) {x <- x^2; x <- x + 5; x <- as.character (x); return (x)} ' –

+1

Có thể trùng lặp: http://stackoverflow.com/questions/7290947/data-manipulation-in-r-in-linq-style – Owen

+0

bản sao có thể có của [cách thực hiện toán tử đường ống chuyển tiếp của F # trong R? ] (http://stackoverflow.com/questions/8896820/how-to-implement-fs-forward-pipe-operator-in-r) –

Trả lời

7

Chúng ta có thể sử dụng Compose từ gói chức năng để tạo ra hành nhị phân riêng của chúng tôi mà không một cái gì đó tương tự như những gì bạn muốn

# 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) } 

Tôi đoán chúng ta có thể về mặt kỹ thuật làm điều này mà không yêu cầu gói chức năng - nhưng nó cảm thấy đúng khi sử dụng Compose cho tác vụ này.

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

Chúng ta có thể loại bỏ hai '%%' symbls trong '% |> % '? Họ trông xấu xí và cồng kềnh. Hoặc là có bất kỳ pecularity cho %% trong R? Tôi không thể tìm thấy lời giải thích trong tài liệu. – Nick

+0

Chúng được yêu cầu. Tôi không biết nó được đề cập đến trong tài liệu hướng dẫn về cách xác định những thứ này nhưng nó ở đâu đó. Các toán tử nhị phân do người dùng định nghĩa sẽ luôn có dạng '% something%' – Dason

5

Tôi nghĩ rằng bạn có thể chỉ muốn viết một hàm để thực hiện các bước bạn mong muốn.

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

Sau đó, chỉ cần gọi complexFunction(x).


Chỉnh sửa để hiển thị những gì R đang làm nội bộ (@mnel) - Cách R phân tích và đánh giá as.character(x^2 + 5) làm những gì bạn muốn

Bạn có thể sử dụng codetools để điều tra những gì R để xem cách các giá trị đang được chuyển đến 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*`) 

Hoặc bạn có thể có đại diện kiểu Lisp để xem cách phân tích cú pháp (và kết quả p assed)

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

Đây là phương pháp lập trình chức năng sử dụng Reduce. Nó thực chất là một ví dụ từ ?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" 

Hoặc thậm chí đơn giản hơn bằng cách sử dụng functional gói và Compose

này là tốt đẹp vì nó sẽ tạo ra các chức năng cho bạn

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

Tôi lưu ý rằng tôi sẽ không xem xét một trong các ứng dụng này gián idiomatically R ish (nếu đó là ngay cả một cụm từ)

0

này làm việc cho R khá giống trong F #:

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

Kể từ khi câu hỏi này được hỏi, các đường ống magrittr đã trở thành vô cùng phổ biến trong R. Vì vậy, ví dụ bạn sẽ là:

library (magrittr) 

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

Lưu ý rằng ký hiệu backquote là vì tôi đang sử dụng các hàm dựng sẵn của R theo nghĩa đen và tôi cần đặc biệt trích dẫn chúng để sử dụng chúng theo cách này. Các hàm được đặt tên thông thường hơn (như exp hoặc nếu tôi đã tạo hàm trợ giúp add) sẽ không cần backquotes và sẽ xuất hiện giống như ví dụ của bạn.

Cũng lưu ý rằng %>% chuyển giá trị đầu vào làm đối số đầu tiên cho hàm tiếp theo tự động, mặc dù bạn có thể thay đổi điều này. Cũng lưu ý rằng hàm R trả về giá trị cuối cùng được tính toán vì vậy tôi không cần phải return hoặc gán phép tính để trả lại giá trị đó.

Điều này giống như các toán tử đặc biệt tốt được xác định bởi các câu trả lời khác, nhưng nó sử dụng một hàm cụ thể được sử dụng rộng rãi trong R bây giờ.

Các vấn đề liên quan