我有一个来自 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
最佳答案
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 Well
gsub
是“global sub”的缩写,它会重复应用该模式。但我使用的模式最多只能匹配一次,所以我们可以使用 singlesub()
。这是一个语法问题,也可能是效率问题。
–
|
您要求的是删除所有标点符号,然后删除字符串末尾的一个或两个字母数字字符。
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=TRUE
ingsub
才能使此模式正常工作,因为它符合 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 的正则表达式基本上就是在没有拼写错误的情况下做同样的事情(以字符串末尾的一个字母为目标)。两者都不会匹配末尾的多个字母。
–
|
-
我想知道您的真实意图是否实际上是删除字符串末尾除 + 数字之外的标点符号。是吗?我MB-13-169454
看到您的输入,而 Tim 的解决方案返回此“代码”不变,这是预期的吗?–
MB-13-169454
作为我不想被操纵的 ID 的示例,因为这将是根患者 ID,而不是重复的–
8253015N/21
,您想保持原样还是退回8253015N
?–
8253015N
–
MB-13-169454
从8253015N/21
字符串末尾的几个字母数字中分辨出来呢?–
|