2017-04-07 47 views
15

Tôi đang cố gắng tìm hiểu chức năng đường ống (%>%).
Khi cố chuyển đổi từ dòng mã này sang dòng mã khác, nó không hoạt động.Đường ống R (%>%) không hoạt động với chức năng sao chép

---- đang R - phiên bản gốc -----

set.seed(1014) 
replicate(6,sample(1:8)) 
    [,1] [,2] [,3] [,4] [,5] [,6] 
[1,] 1 3 7 4 5 1 
[2,] 2 8 4 2 4 2 
[3,] 5 4 8 5 8 5 
[4,] 3 1 2 1 1 7 
[5,] 4 6 3 7 7 3 
[6,] 6 5 1 3 3 8 
[7,] 8 7 5 8 6 6 
[8,] 7 2 6 6 2 4 

---- đang R - recoded với ống ----

> sample(1:8) %>% replicate(6,.) 
    [,1] [,2] [,3] [,4] [,5] [,6] 
[1,] 7 7 7 7 7 7 
[2,] 3 3 3 3 3 3 
[3,] 2 2 2 2 2 2 
[4,] 1 1 1 1 1 1 
[5,] 5 5 5 5 5 5 
[6,] 4 4 4 4 4 4 
[7,] 8 8 8 8 8 8 
[8,] 6 6 6 6 6 6 

ý rằng khi sử dụng đường ống, việc lấy mẫu không làm việc cho tôi cùng một vector trên.

+5

Trong lần đầu tiên mã, bản sao đang thực thi hàm mẫu 6 lần. Trong mã thứ hai, bạn được cung cấp đầu ra cho hàm mẫu và sao chép đầu ra đó 6 lần. – student

Trả lời

19

Điều đó được mong đợi. sao chép mong đợi một biểu thức, nhưng khi sử dụng toán tử đường ống như bạn chỉ cần dán kết quả của cuộc gọi đến sample() đến replicate. Vì vậy, bạn nhận được 6 lần kết quả tương tự.

Bạn phải sử dụng quote() để chuyển biểu thức để nhân rộng thay vì kết quả, nhưng bạn không nên quên đánh giá từng lần lặp lại biểu thức đó.

quote(sample(c(1:10,-99),6,rep=TRUE)) %>% 
    replicate(6, .) %>% 
    sapply(eval) 

Cung cấp:

[,1] [,2] [,3] [,4] [,5] [,6] 
[1,] 5 2 10 10 9 2 
[2,] 4 3 1 3 -99 1 
[3,] 10 2 3 8 2 4 
[4,] -99 1 6 2 10 3 
[5,] 8 -99 1 9 4 6 
[6,] 4 10 8 1 -99 8 

gì xảy ra ở đây:

  • các đường ống sẽ gửi và biểu thức để tái tạo mà không đánh giá nó.
  • sao chép lặp lại biểu thức đó và trả về danh sách có 6 lần biểu thức đó nhưng không đánh giá nó.
  • sapply (eval) đi qua danh sách và thực hiện từng biểu thức trong danh sách đó.

Trong câu hỏi trước đó của bạn (ví dụ: khi sử dụng data.frame), bạn có thể làm ví dụ:

quote(sample(c(1:10,-99),6,rep=TRUE)) %>% 
    replicate(6, .) %>% 
    data.frame 

Bây giờ chức năng data.frame sẽ buộc các biểu thức được thực thi, nhưng bạn cũng kết thúc với tên biến khủng khiếp, tức là biểu thức chính nó.

Nếu bạn muốn tìm hiểu thêm về các vấn đề ở đây, bạn sẽ phải đi sâu vào những gì được gọi là "đánh giá lười biếng" và cách được xử lý chính xác bởi nhà điều hành đường ống. Nhưng trong tất cả sự trung thực, tôi thực sự không thấy bất kỳ lợi thế của việc sử dụng các nhà điều hành đường ống trong trường hợp này. Nó thậm chí còn không đọc được nữa.

Theo nhận xét của Frank: Bạn có thể sử dụng hỗn hợp đường ống và lồng các hàm để tránh sapply. Nhưng vì điều đó, bạn cần phải chứa các chức năng lồng nhau bên trong một khối mã hoặc các nhà điều hành đường ống sẽ không xử lý nó một cách chính xác:

quote(sample(c(1:10,-99),6,rep=TRUE)) %>% { 
    replicate(6, eval(.)) } 

Rất thú vị, nhưng IMHO không thực sự hữu ích ...

+0

Cảm ơn bạn rất nhiều. Nghe có lý! Chỉ cần cố gắng tìm hiểu công cụ này. Yeah, có thể không đáng để sử dụng đường ống ở đây nhưng tôi chỉ học thôi. – phage

+0

Tôi không nghĩ là cần thiết: 'trích dẫn (mẫu (c (1: 10, -99), 6, rep = TRUE))%>% {sao chép (6, eval (.))}' – Frank

+1

@Frank quên bình luận trước của tôi, tôi bỏ lỡ '{}' và thực tế 'eval()' bây giờ được lồng trong 'replicate'. Điều đó hoạt động thực sự, nhưng đây là một nửa đường ống, một nửa không, do đó, nó làm cho cảm giác ít hơn. Cảm ơn bạn đã đề cập đến nó mặc dù, đó là một trường hợp thú vị. Và một ví dụ khác là tại sao nhà điều hành đường ống đó là một loại giun mà tôi không muốn mở. Tuy nhiên, tôi đã thêm đề xuất của bạn vào bài đăng. –

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