R语言对数据框两列执行正则替换千分位点时函数异常如何解决
问题根因
你的代码存在两个核心错误,直接触发警告、导致结果不符合预期:
- 警告触发原因:R中的
if()仅支持接收长度为1的逻辑判断值,你通过lapply传入函数的x是整列长度为6的字符向量,str_detect(x, '\\.\\d{3}')会返回长度为6的逻辑向量,因此if()只会取该向量第一个元素的结果作为整列的判断依据——只要列的第一个元素匹配千分位模式,整列所有元素都会执行替换逻辑,完全不考虑其他元素是否需要替换。 - 替换逻辑错误:你写的
sub('.', '', x, fixed = TRUE)是删除字符串中出现的第一个英文点,完全没有校验这个点是否是「后面紧跟3位数字的千分位点」,会把普通小数的小数点也误删。
修正方法
不需要写分支判断,直接用带正向预查的正则做向量化替换即可,只删除符合「英文点+后续紧跟3位连续数字」规则的千分位分隔点,其他字符完全保留:
library(stringr) # 对两列应用替换规则 DF[, 2:3] <- lapply(DF[, 2:3], function(col) { # 正则含义:匹配后面紧跟3位数字的英文点,替换为空 str_replace(col, "\\.(?=\\d{3})", "") })
运行后得到的结果和预期完全一致:
PRODUCT_ID LOC_1 LOC_2 1 A125 2000.00 usd pr. kg 45000.00 usd pr. kg 2 A444 37.61 usd pr. piece 3000.00 usd pr. piece 3 A744 46.58 usd pr. item 780.00 usd pr. item 4 B12 327% 505% 5 C7 0 0% 6 D1 <NA> <NA>
正则说明:
\\.(?=\\d{3})中的(?=\\d{3})是正向零宽断言,只会定位后面紧跟3位数字的英文点,不会消耗点后面的数字字符,因此不会改动金额小数部分的点(金额小数点点后通常只有2位,不会触发匹配)。
内容的提问来源于stack exchange,提问作者Frodo
相关产品推荐
相关产品推荐

