使用qdapRegex的rm_between在mutate中提取字符串失败,求原因
问题原因分析
你的问题核心出在对rm_between返回值的索引方式和dplyr的向量化操作逻辑上,具体来说:
当你把
rm_between作用于整个Values向量时,它返回的是一个长度等于数据框行数的列表:- 对于第1、2行没有"Height : "的字符串,对应的列表元素是空的
list() - 第3行匹配成功,对应的列表元素是
list("13")
- 对于第1、2行没有"Height : "的字符串,对应的列表元素是空的
你写的
rm_between(...)[[1]]是直接取这个大列表的第一个元素(也就是第1行的空列表),而不是对每个列表元素单独提取第一个值。所以当if_else判断第3行满足条件时,它会把这个空列表的[[1]](也就是NULL,在数据框中显示为<NA>)赋值给该行,而前两行的"None"是字符型,最终就出现了第三行显示<NA>的情况。
解决方法
这里有两种更靠谱的处理方式:
方法一:用purrr逐元素处理rm_between的返回列表
我们可以用purrr::map_chr遍历rm_between返回的列表,对每个元素提取第一个值(如果有的话),没有的话返回NA_character_,再用coalesce把NA替换成"None":
library(dplyr) library(qdapRegex) library(purrr) # 重新创建测试数据框 ID <- c("1","2","3") Values <- c("A","B","Height : 13cm Width : 14cm") dfTest <- data.frame(ID,Values) # 正确处理 dfTest <- dfTest %>% mutate( # 先提取每个行的匹配结果,没有则返回NA Height_temp = map_chr(rm_between(Values, "Height : ", "cm", extract = TRUE), ~if (length(.x) > 0) .x[[1]] else NA_character_), # 把NA替换成"None" Height = coalesce(Height_temp, "None") ) %>% select(-Height_temp) # 删掉临时列
运行后你会得到预期结果:
ID Values Height 1 1 A None 2 2 B None 3 3 Height : 13cm Width : 14cm 13
方法二:用stringr::str_extract更简洁处理
如果你的匹配规则比较固定(就是提取"Height : "和"cm"之间的数字),用stringr包的str_extract会更直接,不需要处理列表:
library(dplyr) library(stringr) dfTest <- dfTest %>% mutate(Height = if_else( str_detect(Values, "Height : "), # 用正则正向预查提取中间的数字 str_extract(Values, "(?<=Height : )\\d+(?=cm)"), "None" ))
这个正则表达式(?<=Height : )\\d+(?=cm)的意思是:匹配前面是"Height : "、后面是"cm"的连续数字,完美提取你想要的"13"。
内容的提问来源于stack exchange,提问作者BroQ
相关产品推荐
相关产品推荐

