在文本中将百分比转换为小数
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}"
检查第二个元素,第四个元素和最后一个元素,你会发现它们没有被改变。
我有几行包含计算规则的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}"
检查第二个元素,第四个元素和最后一个元素,你会发现它们没有被改变。