具有ifelse行为的magrittr管道(%>%)的原因?

时间:2017-11-04 10:49:44

标签: r magrittr

我在使用条件和ifelse分支中的转发结果的情况下使用带有管道的ifelse。下面是一个简化版本:ifelse + pipe似乎只处理不同于.的条件,如果放在花括号内。  

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"

我最初的目标:

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] ""

使用{}对我来说已经足够了,但我想了解这种行为的原因。

修改 虽然this问题讨论了一个相关主题,但我最初看到将ifelse放在花括号中的想法,在表达式/函数调用中使用简单.或使用.之间没有区别。是我的问题的主要观点。

3 个答案:

答案 0 :(得分:7)

magrittr文档说明当在嵌套函数中使用点时,它的行为与您所看到的一样。

  

将点用于辅助目的   通常,除了lhs本身的值之外,在rhs调用中还需要lhs的某些属性或属性,例如:行数或列数。在rhs调用中多次使用点占位符是完全有效的,但是通过设计,在嵌套函数调用中使用它时行为略有不同。 特别是,如果占位符仅用于嵌套函数调用,则lhs也将作为第一个参数放置! 其原因在于大多数用例这产生了最可读的代码。

例如,iris %>% subset(1:nrow(.) %% 2 == 0)相当于iris %>% subset(., 1:nrow(.) %% 2 == 0),但稍微更紧凑。通过将rhs括在大括号中可以否决这种行为。例如,1:10 %>% {c(min(.), max(.))} is equivalent to c(min(1:10), max(1:10))

所以推荐的解决方案实际上是使用你已经找到的大括号。

逻辑评估似乎是ifelse内的单独函数调用,因此也是它的行为原因。

答案 1 :(得分:2)

我认为错误信息非常清楚。

  • 当您使用{}时,.中的{}将替换为%>%的左侧。

  • 当您调用不带{}的函数时,第一个参数是lhs,而您明确编码的其他参数将向右移动,此外(see here):

  

LHS需要在第一个以外的位置,可以使用   dot,'。',作为占位符。

因此,FALSE %>% ifelse(. == TRUE, 'true', 'false')实际上是在调用:

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

FALSE %>% {ifelse(. == TRUE, 'true', 'false')}实际上是在呼叫:

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

答案 2 :(得分:1)

也许这会让你的情况更令人满意:

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