我有几行data.frame,其中包含计算规则。在该字符串中,我需要转换文本,如:
"{p500} * 65% >= {q600}"
到
"{p500} * 0.65 >= {q600}"
我是正则表达式的新手,但我认为 gsub 会对此有所帮助。 有人可以帮忙吗?
答案 0 :(得分:6)
您可以使用gsubfn
对正则表达式进行计算:
library(gsubfn)
gsubfn("(\\d+)%", function(x) strtoi(x)/100,"{p500} * 9% >= {q600}")
[1] "{p500} * 0.09 >= {q600}"
请注意,捕获组值将通过x = \\1
如果您的文字与您提供的示例一致,则可以在base
中执行多个gsub,例如@snoram建议:
gsub("(\\d)%","0.0\\1",gsub("(\\d{2})%","0.\\1","{p500} * 9% >= {q600}"))
[1] "{p500} * 0.09 >= {q600}"
(\\d{2})
正好匹配2位数,括号创建一个可以在gsub中稍后调用的组。通过在替换中调用\\1
,您将返回引用在原始字符串中捕获的组。外部gsub (\\d)%
恰好匹配1位数,在这种情况下替换额外的0。
我自己的正则表达式还比较新,但我发现这个备忘单很有帮助:R Regular Expressions
答案 1 :(得分:3)
base-R中的简单解决方案,但使用(可选)magrittr
以提高可读性
# data + library
str <- c("{p500} * 65% >= {q600}", "{p500} * 9% >= {q600}")
library(magrittr)
# Apply gsub twice:
str %>%
gsub("(\\d{2})%", "0\\.\\1", .) %>%
gsub("(\\d{1})%", "0\\.0\\1", .)
[1] "{p500} * 0.65 >= {q600}" "{p500} * 0.09 >= {q600}"
编辑
鉴于评论中的新案例,我想最好将上面的简单方法放在后面并尝试不同的方法。这是一个快速而肮脏的例子(仍然依赖于良好的ol&#39; base-R):
# New data
str <- c(
"{p500} * 65% >= {q600}",
"{p500} * 9% >= {q600}",
"{p500} * 190% >= {q600}",
"{p500} * 2.4% >= {q600}")
# Quick and dirty
strmat <- do.call(rbind, strsplit(str, " "))
strmat[, 3] <- as.double(gsub("%", "", lapply(strsplit(str, " "), "[", 3))) / 100
apply(strmat, 1, paste, collapse=" ")
[1] "{p500} * 0.65 >= {q600}" "{p500} * 0.09 >= {q600}" "{p500} * 1.9 >= {q600}"
[4] "{p500} * 0.024 >= {q600}"
答案 2 :(得分:1)
您可以使用regmatches
。首先捕获那些你需要的数字,然后除以100,使它们成为小数点。然后用小数点替换它们:
警告。这取代了您拥有的原始str
。也许有必要创建副本:
str <- c("{p500} * 65% >= {q600}","{p500} * 9% >= {q600}",
"{p500} * 190% >= {q600}","{p500} * 2.4% >= {q600}")
str1=str
regmatches(str1,regexpr("\\d\\S*%",str))=as.numeric(sub(".*?(\\d\\S*)%.*","\\1",str))/100
str1
[1] "{p500} * 0.65 >= {q600}" "{p500} * 0.09 >= {q600}"
[3] "{p500} * 1.9 >= {q600}" "{p500} * 0.024 >= {q600}"
如果其他人错过了%
符号,他们需要保持不变:
str <- c("{p500} * 65% >= {q600}","{p500} * 65 >= {q600}","{p500} * 9% >= {q600}",
"{p500} * 190 >= {q600}", "{p500} * 190% >= {q600}","{p500} * 2.4% >= {q600}",
"{p500} * 2.4 >= {q600}")
str1=str # Create a copy
m=regexpr("\\d\\S*%",str)# Find only those that contain % sign
regmatches(str1,m)=as.numeric(sub("%","",regmatches(str,m)))/100
str1
[1] "{p500} * 0.65 >= {q600}" "{p500} * 65 >= {q600}"
[3] "{p500} * 0.09 >= {q600}" "{p500} * 190 >= {q600}"
[5] "{p500} * 1.9 >= {q600}" "{p500} * 0.024 >= {q600}"
[7] "{p500} * 2.4 >= {q600}"
检查第二个元素,第四个元素和最后一个元素,您将看到它们没有被更改。