在 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)substringr 删除/替换函数限制通用字符类的一些选项:

(g)subperl=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)

然后将applygsub 结合使用。

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 删除除句点之外的所有标点符号的主要内容,如果未能解决你的问题,请参考以下文章

删除 R 中除撇号外的所有标点符号

Rails 去除除数字逗号和小数点以外的所有内容

使用 gsub 删除 R 中第一个空格之前的所有字符串

删除除给定查询获取的所有记录之外的所有记录

删除扩展的 ASCII 字符。 Linux 脚本 (128-255)

如何在 R 中使用 gsub 从字符串中删除非数字字符?