R中magrittr管道传入if返回未执行管道的问题如何解决?
问题根因
你遇到的问题是magrittr管道的特殊语法导致的:当%>%的左侧为单独的.时,整个表达式不会立即求值,而是会返回一个「函数序列(functional sequence)」对象,也就是你看到的提示里的可调用函数,而非执行结果。
你在if的TRUE分支里写的. %>% round()本质是创建了一个单参数函数,你没有主动传入参数调用它,自然就返回了函数本身,而不是把当前的x传入执行。
解决方法
方法1:主动调用生成的管道函数
如果要保留你现有的if写法,只需要在构造完管道函数后,用当前的.作为参数主动调用即可,这种写法支持你在管道内加任意多的步骤:
library(magrittr) maybe_round = function(x, round = TRUE){ x %>% `if`( round, # 构造管道函数后直接加(.)传入当前值执行 (. %>% round(2) %>% `*`(100) %>% as.integer())(.), . ) } # 测试 > maybe_round(5.346, TRUE) [1] 535 > maybe_round(5.346, FALSE) [1] 5.346
方法2:用purrr::when简化条件分支写法
purrr::when原生支持管道内的条件分支,每个分支的表达式会自动接收传入的值作为.x,不需要手动构造管道函数,写法更简洁:
library(magrittr) library(purrr) maybe_round = function(x, round = TRUE){ x %>% when( round ~ .x %>% round(2) %>% `*`(100) %>% as.integer(), ~ .x # 不满足条件时直接返回原值 ) }
方法3:用大括号包裹完整逻辑
你也可以用大括号把整个条件判断包裹起来,直接对管道传入的.做操作,完全规避函数序列的问题:
maybe_round = function(x, round = TRUE){ x %>% { if (round) { . %>% round(2) %>% `*`(100) %>% as.integer() } else { identity } } %>% exec(.) }
内容的提问来源于stack exchange,提问作者Migwell
相关产品推荐
相关产品推荐

