如何让purrr::possibly()执行失败时返回映射的输入对象?
解决嵌套数据框中选择性移除列的问题
你的问题核心在于possibly()的otherwise参数需要的是具体的值,而不是函数——所以直接传function(x){x}只会返回这个函数对象,不会执行它。不过其实有更巧妙的方法,不用显式的错误处理就能搞定!
方法1:用dplyr::any_of()(最简洁推荐)
dplyr的any_of()函数专门用来处理这种“列存在就操作,不存在就忽略”的场景。它会自动检查列是否存在,不存在的话不会抛出错误,直接跳过,完全贴合你的需求:
library(tidyverse) # 先构造你的示例数据框 mtcars %>% group_by(cyl) %>% nest -> tmp tmp[3,'data'][[1]][[1]] <- dplyr::select(tmp[3,'data'][[1]][[1]], -mpg) # 关键代码:用any_of处理列移除 tmp %>% mutate(data2 = map(data, ~select(., -any_of("mpg"))))
执行后,有mpg列的子数据框会自动移除该列,没有mpg列的子框则保持原样,一步到位。
方法2:自定义函数结合possibly()
如果你还是想用possibly(),可以把逻辑包装在匿名函数里,让otherwise返回当前的子数据框。这里需要把当前子框作为参数传入,让possibly能捕获错误并返回原数据:
tmp %>% mutate(data2 = map(data, function(x) { possibly(~select(., -mpg), otherwise = x)(x) }))
或者更简洁的写法,直接在possibly里绑定当前子框参数:
tmp %>% mutate(data2 = map(data, ~possibly(select, otherwise = .x)(.x, -mpg)))
思路是:对每个子数据框.x,用possibly包裹select函数,当select(.x, -mpg)出错时,直接返回.x本身。
方法3:先检查列是否存在再操作
另一种直观的思路是先判断子数据框里有没有mpg列,再决定是否移除:
tmp %>% mutate(data2 = map(data, ~if ("mpg" %in% colnames(.)) { select(., -mpg) } else { . }))
这种方法逻辑清晰,适合需要添加更复杂判断条件的场景。
内容的提问来源于stack exchange,提问作者ohnoplus
相关产品推荐
相关产品推荐

