在 R 中,使用 gsub 删除除句点之外的所有标点符号
Posted
技术标签:
【中文标题】在 R 中,使用 gsub 删除除句点之外的所有标点符号【英文标题】:in R, use gsub to remove all punctuation except period 【发布时间】:2014-02-27 07:48:13 【问题描述】:我是 R 新手,所以希望你能帮助我。
我想使用 gsub 删除除句点和减号之外的所有标点符号,以便我可以在数据中保留小数点和负号。
示例
我的数据框 z 有以下数据:
[,1] [,2]
[1,] "1" "6"
[2,] "2@" "7.235"
[3,] "3" "8"
[4,] "4" "$9"
[5,] "£5" "-10"
我想使用gsub("[[:punct:]]", "", z)
删除标点符号。
电流输出
> gsub("[[:punct:]]", "", z)
[,1] [,2]
[1,] "1" "6"
[2,] "2" "7235"
[3,] "3" "8"
[4,] "4" "9"
[5,] "5" "10"
不过,我希望保留“-”符号和“.”。签名。
期望的输出
PSEUDO CODE:
> gsub("[[:punct:]]", "", z, except(".", "-") )
[,1] [,2]
[1,] "1" "6"
[2,] "2" "7.235"
[3,] "3" "8"
[4,] "4" "9"
[5,] "5" "-10"
有什么想法可以让某些字符免于 gsub() 函数吗?
【问题讨论】:
相信这篇文章会回答你的问题:***.com/questions/8697079/… 尝试双重否定,例如:gsub("[^[:^punct:].]", "", x, perl = TRUE)
。
“z”是matrix
还是data.frame
?
【参考方案1】:
你可以试试这个代码。我发现它很方便。
x <- c('6,345', '7.235', '8', '$9', '-10')
gsub("[^[:alnum:]\\-\\.\\s]", "", x)
[1] "6345" "7.235" "8" "9" "-10"
x <- c('1', '2@', '3', '4', '£5')
gsub("[^[:alnum:]\\-\\.\\s]", "", x)
[1] "1" "2" "3" "4" "5"
此代码gsub("[^[:alnum:]]", "", x)) 删除不包含字母数字术语的所有内容。然后我们添加到例外列表中。这里我们添加连字符(\-)、句号(\.) 和空格(\s) 得到gsub("[^[:alnum:]\-\.\s]", "", x)。现在它会删除所有不是字母数字、连字符、句号和空格的内容。
【讨论】:
你能解释一下你的代码的更多细节吗? 添加了解释和一个例子。【参考方案2】:以下是在 R 中使用基本 R (g)sub
和 stringr
删除/替换函数限制通用字符类的一些选项:
(g)sub
与 perl=TRUE
您可以将[[:punct:]]
括号表达式与[:punct:]
POSIX 字符类一起使用,并使用(?!\.)
负前瞻来限制它,这将要求右侧紧随其后的字符不等于.
:
(?!\.)[[:punct:]] # Excluding a dot only
(?![.-])[[:punct:]] # Excluding a dot and hyphen
要匹配一个或多个匹配项,请使用非捕获组对其进行包装,然后将+
量词设置为该组:
(?:(?!\.)[[:punct:]])+ # Excluding a dot only
(?:(?![.-])[[:punct:]])+ # Excluding a dot and hyphen
请注意,当您删除找到匹配项时,两个表达式将产生相同的结果,但是,当您需要替换为其他字符串/字符时,量化将允许使用一次替换模式来更改整个连续的字符块。
带有stringr
替换/删除功能
在详细介绍之前,请注意与 (g)sub
一起使用的 PCRE [[:punct:]]
不会匹配由 ICU regex library 提供支持的 stringr
正则表达式函数中的相同字符。您需要改用[\pP\pS]
,请参阅R/regex with stringi/ICU: why is a '+' considered a non-[:punct:] character?
ICU 正则表达式库有一个很好的功能,可以与字符类一起使用,称为 character class subtraction。
因此,您编写了您的字符类,例如所有标点匹配类,例如 [\pP\pS]
,然后您想要“排除”(=减去)一个字符或两个或三个字符,或者字符的整个子类。您可以使用两种表示法:
[\pP\pS&&[^.]] # Excluding a dot
[\pP\pS--[.]] # Excluding a dot
[\pP\pS&&[^.-]] # Excluding a dot and hyphen
[\pP\pS--[.-]] # Excluding a dot and hyphen
要使用这种方法匹配 1+ 个连续出现,您不需要任何包装组,只需使用 +
:
[\pP\pS&&[^.]]+ # Excluding a dot
[\pP\pS--[.]]+ # Excluding a dot
[\pP\pS&&[^.-]]+ # Excluding a dot and hyphen
[\pP\pS--[.-]]+ # Excluding a dot and hyphen
见R demo tests with outputs:
x <- "Abc.123#&*xxx(x-y-z)???? some@other!chars."
gsub("(?!\\.)[[:punct:]]", "", x, perl=TRUE)
## => [1] "Abc.123xxxxyz someotherchars."
gsub("(?!\\.)[[:punct:]]", "~", x, perl=TRUE)
## => [1] "Abc.123~~~xxx~x~y~z~~~~~ some~other~chars."
gsub("(?:(?!\\.)[[:punct:]])+", "~", x, perl=TRUE)
## => [1] "Abc.123~xxx~x~y~z~ some~other~chars."
library(stringr)
stringr::str_remove_all(x, "[\\pP\\pS&&[^.]]") # Same as "[\\pP\\pS--[.]]"
## => [1] "Abc.123xxxxyz someotherchars."
stringr::str_replace_all(x, "[\\pP\\pS&&[^.]]", "~")
## => [1] "Abc.123~~~xxx~x~y~z~~~~~ some~other~chars."
stringr::str_replace_all(x, "[\\pP\\pS&&[^.]]+", "~") # Same as "[\\pP\\pS--[.]]+"
## => [1] "Abc.123~xxx~x~y~z~ some~other~chars."
【讨论】:
【参考方案3】:另一种思考方式是您想保留什么?您可以使用正则表达式来保留和省略信息。我有很多数据帧,我需要一次性清除单元并从多行转换,我发现在这些情况下使用apply
系列中的东西最容易。
重新创建示例:
a <- c('1', '2@', '3', '4', '£5')
b <- c('6', '7.235', '8', '$9', '-10')
z <- matrix(data = c(a, b), nrow = length(a), ncol=2)
然后将apply
与gsub
结合使用。
apply(z, 2, function(x) as.numeric(gsub('[^0-9\\.\\-]', '', x)))
[,1] [,2]
[1,] 1 6.000
[2,] 2 7.235
[3,] 3 8.000
[4,] 4 9.000
[5,] 5 -10.000
这指示 R 匹配除数字、句点和连字符/破折号以外的所有内容。就个人而言,我发现它在这些情况下更清洁、更容易使用,并提供相同的输出。
此外,文档对这些强大但令人困惑的正则表达式有很好的解释。
https://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.html
或?regex
【讨论】:
该链接只是托管 R 文档。使用?regex
可以看到相同的内容。【参考方案4】:
您可以像这样放回一些匹配项:
sub("([.-])|[[:punct:]]", "\\1", as.matrix(z))
X..1. X..2.
[1,] "1" "6"
[2,] "2" "7.235"
[3,] "3" "8"
[4,] "4" "9"
[5,] "5" "-10"
我在这里保留.
和-
。
我猜,下一步是强制你得到一个数字矩阵,所以在这里我将这两个步骤结合起来:
matrix(as.numeric(sub("([.-])|[[:punct:]]", "\\1", as.matrix(z))),ncol=2)
[,1] [,2]
[1,] 1 6.000
[2,] 2 7.235
[3,] 3 8.000
[4,] 4 9.000
[5,] 5 -10.000
【讨论】:
感谢您,完美运行。我只需要第一部分。你能解释一下这里发生了什么吗?就像我理解你正在分离 .和 - 来自:punct: 但不确定如何.. \\1 是使用 () 的正则表达式中最后一次捕获的语法它表示任何匹配的内容,用它替换它。我只放了“。”和组 () 中的“-”,因此 \\1 将替换 .-(由相同的值),因此将它们保留在此处。 @CrayonConstantinople 我不确定我的“英语”解释是否正确,也许更好地阅读关于组捕获的信息here。 感谢您的帮助。出于兴趣,是否需要进行很多更改才能将其更改为 data.frame 而不是矩阵? @CrayonConstantinople 只需在此应用as.data.frame
。以上是关于在 R 中,使用 gsub 删除除句点之外的所有标点符号的主要内容,如果未能解决你的问题,请参考以下文章