我有一个来自 35 家不同医院的 ID 变量,因此该变量有各种不同的排列,有时它具有相同的根 ID 号和辅助线号 – 例如 -1、/a、_1 等。

我想删除标点符号以及标点符号后面的任何内容,只留下根 ID 号。

我目前已经设法为每个不同的迭代写出单独的代码行,但我想知道是否有更优雅的方法,以便明年当数据进入时我不需要检查不同的安排?

在别人的问题上,我设法找到了一种方法来删除括号和括号内的所有文本,但我似乎无法弄清楚如何为我的目的操作它

df$patid<- gsub("\\s*\\([^\\)]+\\)","",df$patid)

我尝试了这两个代码,但没有成功

df$patid<- gsub("\\[:punct:]s*$","", df$patid)
df$patid<- gsub("\\[:alnum:]s*$","", df$patid)

我也尝试了该clean功能,它删除了所有标点符号,但保留了后面的数字/字符,所以不是这样。

我当前代码的示例(并非所有可能的迭代) – 这些确实有效

df$patid<- gsub("\\-1$", "", df$patid)
df$patid<- gsub("\\-2$", "", df$patid)
df$patid<- gsub("\\-3$", "", df$patid)
df$patid<- gsub("\\-a$", "", df$patid)
df$patid<- gsub("\\-A$", "", df$patid)
df$patid<- gsub("\\-b$", "", df$patid)
df$patid<- gsub("\\-B$", "", df$patid)
df$patid<- gsub("\\b", "", df$patid)
df$patid<- gsub("\\/dd", "", df$patid)

不受束缚gsub,可以接受不同的方法。

身份证号码示例

patid<- c("MB-13-169454", "MB-13-179455", "MB-13-212235.1", "MB-13-212235.2", "MB-13-224683", "570548260-2", "570548260-3", "1458629P-2", "1139093D-2", "8253015N/2", "8253015N/3", "M255858/1", "M255858/2", "8494392Q/2", "9296741B/2", "04152341421/A", "04152341421/B", "04152640475/B", "04152821164/A", "G140381883_1", "G140381883_2", "G140880774_1", "G140880774_2")

如果这个问题已经在别处得到解答,请见谅

5

  • -我想知道您的真实意图是否实际上是删除字符串末尾除 + 数字之外的标点符号。是吗?我MB-13-169454看到您的输入,而 Tim 的解决方案返回此“代码”不变,这是预期的吗?


    – 


  • Tim 的解决方案完全符合我的期望。我把MB-13-169454作为我不想被操纵的 ID 的示例,因为这将是根患者 ID,而不是重复的


    – 

  • 那么,如果有的话8253015N/21,您想保持原样还是退回8253015N


    – 

  • 理想情况下返回为8253015N


    – 

  • 那么我们如何MB-13-1694548253015N/21字符串末尾的几个字母数字中分辨出来呢?


    – 


最佳答案
2

您所描述的文字正则表达式为:

[[:punct:]][^[:punct:]]*$

这将匹配最后一个标点符号,后跟其后的任何内容,直到字符串末尾。

patid <- c("MB-13-169454", "MB-13-179455", "MB-13-212235.1", "MB-13-212235.2", "MB-13-224683", "570548260-2", "570548260-3", "1458629P-2", "1139093D-2", "8253015N/2", "8253015N/3", "M255858/1", "M255858/2", "8494392Q/2", "9296741B/2", "04152341421/A", "04152341421/B", "04152640475/B", "04152821164/A", "G140381883_1", "G140381883_2", "G140880774_1", "G140880774_2")
output <- sub("[[:punct:]][^[:punct:]]*$", "", patid)
output

 [1] "MB-13-169454" "MB-13-179455" "MB-13-212235" "MB-13-212235" "MB-13-224683"
 [6] "570548260"    "570548260"    "1458629P"     "1139093D"     "8253015N"    
[11] "8253015N"     "M255858"      "M255858"      "8494392Q"     "9296741B"    
[16] "04152341421"  "04152341421"  "04152640475"  "04152821164"  "G140381883"  
[21] "G140381883"   "G140880774"   "G140880774"  

2

  • 谢谢!我知道这是正则表达式的问题,但我就是看不懂。请问您为什么使用sub而不是gsub


    – 


  • 1
    @missanita Wellgsub是“global sub”的缩写,它会重复应用该模式。但我使用的模式最多只能匹配一次,所以我们可以使用 single sub()。这是一个语法问题,也可能是效率问题。


    – 

您要求的是删除所有标点符号,然后删除字符串末尾的一个或两个字母数字字符

gsub("[[:punct:]][[:alnum:]]{1,2}$", "", x)

请参阅[[:punct:]][[:alnum:]]{1,2}$符合 TRE 的模式匹配标点符号 ( [[:punct:]]),然后匹配一个或两个字母数字 ( ),然后断言该字母数字字符后[[:alnum:]]{1,2}是否有字符串结尾 ( )。请参阅$

要删除字符串末尾的任何标点符号及其后的文本,可以使用

gsub("[\\p{S}\\p{P}]+[^\\p{S}\\p{P}]*$", "", x, perl=TRUE)

注意:您也可以使用带函数的相同模式stringr::str_replace_all。此外,您必须使用perl=TRUEingsub才能使此模式正常工作,因为它符合 PCRE 标准,而不是 TRE 标准。

参见

细节

  • [\p{S}\p{P}]+– 一个或多个数学符号或标点符号正确字符(请注意,默认引擎使用[:punct:]包含这两个 Unicode 类别的 POSIX 兼容版本,但正则stringr表达式函数中使用的 ICU 正则表达式引擎不符合 POSIX 并且行为不同,这就是我建议这种模式的原因)
  • [^\p{S}\p{P}]*– 零个或多个除数学符号或标点符号专有字符之外的字符
  • $– 字符串结束。

查看R 演示

patid <- c("MB-13-169454", "MB-13-179455", "MB-13-212235.1", "MB-13-212235.2", "MB-13-224683", "570548260-2", "570548260-3", "1458629P-2", "1139093D-2", "8253015N/2", "8253015N/3", "M255858/1", "M255858/2", "8494392Q/2", "9296741B/2", "04152341421/A", "04152341421/B", "04152640475/B", "04152821164/A", "G140381883_1", "G140381883_2", "G140880774_1", "G140880774_2")

gsub("[\\p{S}\\p{P}]+[^\\p{S}\\p{P}]*$", "", patid, perl=TRUE)

输出:

 [1] "MB-13"        "MB-13"        "MB-13-212235" "MB-13-212235" "MB-13"       
 [6] "570548260"    "570548260"    "1458629P"     "1139093D"     "8253015N"    
[11] "8253015N"     "M255858"      "M255858"      "8494392Q"     "9296741B"    
[16] "04152341421"  "04152341421"  "04152640475"  "04152821164"  "G140381883"  
[21] "G140381883"   "G140880774"   "G140880774"  

您可能感到困惑的其他信息:

10

  • 1
    嗨,Wiktor,我明白你的代码是如何工作的,但这不是我想要的。不过还是谢谢你


    – 

  • @missanita 此解决方案满足了您在标题中提出的要求。我在答案顶部添加了您实际想要要求的内容。看起来您只是想删除一个标点符号,然后删除字符串末尾的一个字母数字字符。


    – 

  • 1
    不,有时我的数据集中标点符号后有几个字符,但它们都出现在字符串的末尾。我不明白你为什么要和我争论我想要什么来解决我的问题…


    – 


  • @missanita 我不是在争论,我只是想通过澄清真正的需求来改进 SO 帖子,以便那些来这里的人可以使用该解决方案来解决他们类似的问题。如果你有这样的多个字符的例子,我不确定 Tim 的解决方案是否能涵盖它们,你能分享至少一个示例字符串和预期结果吗?


    – 

  • 1
    @missanita 我可以插话吗… Tim 的[[:punct:]][^[[:punct:]]]*$正则表达式在我看来很令人困惑,实际上[^[[:punct:]]]*会匹配一个既不是[(冗余的)也不是标点符号的字符,后面跟着]*任意数量的非右括号字符。该构造更像是拼写错误,只会匹配末尾的一个非标点符号,请参阅。如果 Tim 的这个正则表达式是您想要的,那么 Wiktor 的正则表达式基本上就是在没有拼写错误的情况下做同样的事情(以字符串末尾的一个字母为目标)。两者都不会匹配末尾的多个字母。


    –