在文本中将百分比转换为小数

Convert percentage to decimal within text

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

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

进入

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

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

您可以使用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,您就是 back-referencing 您在原始字符串中捕获的组。外部 gsub (\d)% 恰好匹配 1 个数字,并在这种情况下替换额外的 0。

我自己对正则表达式还是比较陌生,但我发现这个 cheat-sheet 很有用:R Regular Expressions

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

编辑

考虑到评论中的新情况,我想最好放弃上面的简单方法并尝试一些不同的方法。这是一个快速而肮脏的例子(仍然依赖于 good ol' 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}"

您可以使用 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}"  

检查第二个元素,第四个元素和最后一个元素,你会发现它们没有被改变。