R语言purrr map对除ID外列应用Blom变换报错排查
报错原因
这个报错来自map_if的语法使用错误,具体有两个核心问题:
purrr::map_if的参数结构固定为map_if(.x, .p, .f, ...):第二个参数.p是筛选待处理元素的判断规则(可以是和输入元素等长的逻辑向量,也可以是返回布尔值的判断函数),第三个参数.f才是要对筛中元素执行的变换函数。你把筛选逻辑names(.) %in% col_names和变换逻辑写在了同一个双侧公式里,程序会把整个公式识别为传入的.f参数,自然无法把双侧公式解析成可执行的变换函数。- 即使拆分公式,直接在
.p位置写names(.) %in% col_names也会出现环境绑定问题,.无法正确指代输入的数据集,不能生成正确的逻辑筛选向量。
另外你提到的map_if(is.numeric, ...)无法排除ID列的问题也很好理解:你用row_number()生成的ID列本身是整数数值类型,is.numeric判断会返回TRUE,自然会被纳入变换范围。
正确实现代码
做数据框批量列变换优先用dplyr的across函数,和你已有的tidyverse代码流适配度最高,不需要额外做格式转换:
library(tidyverse) library(rcompanion) data("mtcars") # 生成带唯一ID列的数据集 mtcars <- mtcars %>% mutate(id = row_number()) # 对除ID列外的所有列应用Blom变换 mtcars_transformed <- mtcars %>% mutate(across( .cols = -id, # 直接按列名排除ID列,不受列类型影响 .fns = ~blom(.x, method = "blom") ))
如果你一定要用map_if实现,需要严格匹配参数规则,注意最后要把返回的列表转回数据框格式:
mtcars_transformed <- mtcars %>% map_if( # 传入和数据集列数等长的逻辑向量,标记需要变换的列 .p = names(.) != "id", .f = ~blom(.x, method = "blom") ) %>% # map_if默认返回列表,需要手动绑定为数据框 bind_cols()
提示:按列名排除的筛选方式比类型判断更精准,后续就算ID列改成字符类型,或者其他数值列有增减,只要ID列名不变,代码就不会出问题。
内容的提问来源于stack exchange,提问作者celilati
相关产品推荐
相关产品推荐

