提取字符串范围极值的函数在dplyr::case_when()中运行异常如何解决
问题原因
你编写的val_from_range函数默认仅支持单个字符串输入,不支持向量批量处理:
- 当你把整列字符向量传入函数时,
str_extract_all会返回所有行匹配到的数字组成的列表,直接调用unlist()会把所有行的数字全部合并为一个长向量,示例中合并后的向量为c(5,6,4,6,9,5),计算得到的全局最小值为4、全局最大值为9 - 后续这个长度为1的结果会被循环填充到所有满足
str_detect(x, "-")条件的行,就出现了不符合预期的输出。
修复方案
方案1:调用时增加rowwise()按行处理
不需要修改原函数,仅在数据处理步骤中增加按行分组逻辑,保证每次给函数传入单个字符串:
tibble(x = c("5-6", "4", "6-9", "5", "NA")) |> rowwise() |> # 增加按行分组 mutate( min = case_when(str_detect(x, "-") ~ val_from_range(x, "min")), max = case_when(str_detect(x, "-") ~ val_from_range(x, "max")) ) |> ungroup() # 处理完成后可取消行分组
方案2:修改原函数为向量化版本
直接改造函数使其原生支持向量输入,调用时不需要额外处理:
val_from_range_vec <- function(.str, .fun = "min"){ # 对向量的每个元素单独处理 purrr::map_dbl(.str, function(s){ nums <- str_extract_all(s, "\\d*\\.?\\d+") |> unlist() |> as.numeric() if (.fun == "min") min(nums) else max(nums) }) } # 直接调用即可得到正确结果 tibble(x = c("5-6", "4", "6-9", "5", "NA")) |> mutate( min = case_when(str_detect(x, "-") ~ val_from_range_vec(x, "min")), max = case_when(str_detect(x, "-") ~ val_from_range_vec(x, "max")) )
两种方案都可以得到你期望的输出结果。
内容的提问来源于stack exchange,提问作者Freddie J. Heather
相关产品推荐
相关产品推荐

