2017-11-04 21 views
7

Tôi đang sử dụng ifelse với đường ống trong một kịch bản mà tôi sử dụng kết quả được chuyển tiếp trong cả hai nhánh điều kiện và ifelse. Dưới đây là một phiên bản đơn giản: có vẻ như ifelse + pipe chỉ xử lý tình trạng khác nhau từ . nếu đặt bên trong dấu ngoặc nhọn.
Lý do cho ống magrittr (%>%) với hành vi ifelse?

library("magrittr") 

FALSE %>% ifelse(., 'true', 'false') 
#> [1] "false" 

FALSE %>% ifelse(. == TRUE, 'true', 'false') 
#> Error in ifelse(., . == TRUE, "true", "false"): unused argument ("false") 

FALSE %>% {ifelse(. == TRUE, 'true', 'false')} 
#> [1] "false" 

mục tiêu ban đầu của tôi:

library("magrittr") 

NULL %>% ifelse(is.null(.), "", as.character(.)) 
#> Error in ifelse(., is.null(.), "", as.character(.)): unused argument (as.character(.)) 

NULL %>% {ifelse(is.null(.), "", as.character(.))} 
#> [1] "" 

Sử dụng {} là đủ tốt cho tôi nhưng tôi muốn hiểu những lý do cho hành vi này.

Edit: Mặc dù this câu hỏi thảo luận về một chủ đề liên quan và ban đầu tôi thấy ý tưởng đưa ifelse bên trong dấu ngoặc nhọn có không có sự khác biệt giữa việc sử dụng đơn giản . hoặc sử dụng . trong một cuộc gọi biểu/chức năng mà là chính điểm của câu hỏi của tôi.

+2

thể bản sao của [R Conditiona l đánh giá khi sử dụng toán tử ống%>%] (https://stackoverflow.com/questions/30604107/r-conditional-evaluation-when-using-the-pipe-operator) – mtoto

Trả lời

6

Tài liệu magrittr nói rằng khi dấu chấm được sử dụng trong hàm lồng nhau gọi nó sẽ hoạt động như bạn đã thấy.

Sử dụng dấu chấm cho các mục đích thứ
Thông thường, một số thuộc tính hoặc tài sản của LHS được mong muốn trong RHS gọi ngoài các giá trị của LHS chính nó, ví dụ số hàng hoặc cột. Nó là hoàn toàn hợp lệ để sử dụng dấu chấm chỗ nhiều lần trong cuộc gọi rhs, nhưng bằng cách thiết kế hành vi là hơi khác nhau khi sử dụng nó bên trong các cuộc gọi hàm lồng nhau. Cụ thể, nếu trình giữ chỗ chỉ được sử dụng trong một cuộc gọi hàm lồng nhau, lhs cũng sẽ được đặt làm đối số đầu tiên! Lý do cho điều này là trong hầu hết các trường hợp sử dụng, điều này tạo ra mã dễ đọc nhất.

Ví dụ: iris %>% subset(1:nrow(.) %% 2 == 0) tương đương với iris %>% subset(., 1:nrow(.) %% 2 == 0) nhưng gọn hơn một chút. Có thể để overrule hành vi này bằng cách kèm theo các rhs trong niềng răng. Ví dụ: 1:10 %>% {c(min(.), max(.))} is equivalent to c(min(1:10), max(1:10)).

Vì vậy, giải pháp được đề xuất thực sự là sử dụng dấu ngoặc nhọn như bạn đã tìm thấy.

Đánh giá lôgic có vẻ là một cuộc gọi chức năng riêng biệt trong số ifelse và do đó lý do hoạt động như vậy.

2

Tôi nghĩ rằng thông báo lỗi khá rõ ràng.

  • Khi bạn sử dụng {}, các . trong {} được thay thế sang trái tay-side của %>%.

  • Khi bạn gọi một chức năng mà không {}, đối số đầu tiên là LHS, trong khi các thông số khác mà bạn mã hóa một cách rõ ràng sẽ di chuyển ngay, và ngoài ra (see here):

LHS là cần thiết ở vị trí khác với vị trí đầu tiên, người ta có thể sử dụng dấu cách , '.', làm trình giữ chỗ.

Do đó, FALSE %>% ifelse(. == TRUE, 'true', 'false') đang thực sự kêu gọi:

ifelse(FALSE, FALSE == TRUE, 'true', 'false') 

FALSE %>% {ifelse(. == TRUE, 'true', 'false')} đang thực sự kêu gọi:

ifelse(FALSE == TRUE, 'true', 'false') 
1

Có lẽ đây sẽ thỏa mãn hơn cho trường hợp của bạn:

NULL %>% as.character %>% inset(length(.)==0, value ="") 
+0

Tôi đã tìm thấy cách tiếp cận tương tự, ngắn hơn một chút khi sử dụng % ||% từ purrr: 'NULL%>% {as.character (. % ||% "")} ' –

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