在文本中将百分比转换为十进制

时间:2018-03-08 14:13:42

标签: r regex string decimal percentage

我有几行data.frame,其中包含计算规则。在该字符串中,我需要转换文本,如:

"{p500} * 65% >= {q600}"

"{p500} * 0.65 >= {q600}"

我是正则表达式的新手,但我认为 gsub 会对此有所帮助。 有人可以帮忙吗?

3 个答案:

答案 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}"  

检查第二个元素,第四个元素和最后一个元素,您将看到它们没有被更改。