Đ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 ...
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