在R中使用purrr::compose结合purrr::partial时select与filter报错问题
问题:purrr compose组合partial函数时select/filter报错
在用purrr::compose组合部分应用的函数时,rename、mutate、head能正常运行,但select和filter会抛出类似object 'milespergallon' not found的错误,调整参数引用或函数顺序都无法解决。
代码示例
library("purrr") library("dplyr") my_func = compose( partial(rename, "milespergallon" = mpg), # 正常工作 partial(mutate, new_col = milespergallon + cyl), # 正常工作 # partial(select, milespergallon, cyl, new_col), # 报错 # partial(filter, cyl > 2), # 报错 # partial(filter, milespergallon > 20), # 报错 head, # 正常工作 .dir = "forward" ) my_func(mtcars)
报错原因
dplyr的select、filter依赖**整洁评估(tidy eval)**机制,它们的参数(列名、过滤条件)需要在数据框的上下文环境中解析。但purrr::partial会立即捕获参数的当前环境,导致这些列名/条件在数据框还未传入时就被求值,自然找不到对应的对象。
而rename、mutate能正常工作,是因为它们的参数结构(比如rename的命名参数)会被当作表达式延迟到数据框传入时才解析,不会提前触发求值。
解决方案
用匿名函数包裹select和filter,让参数在数据框传入后再解析:
library("purrr") library("dplyr") my_func = compose( partial(rename, "milespergallon" = mpg), partial(mutate, new_col = milespergallon + cyl), function(df) select(df, milespergallon, cyl, new_col), # 替换partial为匿名函数 function(df) filter(df, cyl > 2), # 替换partial为匿名函数 function(df) filter(df, milespergallon > 20), # 替换partial为匿名函数 head, .dir = "forward" ) my_func(mtcars)
运行后即可得到预期输出:
milespergallon cyl disp hp drat wt qsec vs am gear carb new_col Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 27.0 Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 27.0 Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 26.8 Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 27.4 Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 26.7 Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 24.1
内容的提问来源于stack exchange,提问作者mattb
相关产品推荐
相关产品推荐

