使用正则表达式删除与国民保险号码格式不符的行

时间:2019-11-11 12:03:18

标签: r regex

从spss切换后,我对R还是相当陌生,但需要在该项目中使用R。我正在从人的excel文件中读取数据,每个人的唯一标识符是他们的英国国民保险号码,但是我需要删除任何不包含正确格式的NINO的行,即AB123456A。

数据中列出了某些类型的“ NINO”,由于它们与格式不完全匹配,因此我需要将其删除。

  • ****** 69B
  • cms1234
  • BCN8888855555
  • AB 123456 A
  • 不适用

我在网上找到了此正则表达式以验证NINO的格式。

  

/ ^ [A-CEGHJ-PR-TW-Z] {1} [A-CEGHJ-NPR-TW-Z] {1} [0-9] {6} [AD] {1} $ / i

我尝试在下面的代码中运行它,但是虽然没有显示错误消息,但它也不会从数据集中删除任何行。

DEP_Programmes %>% 
  filter(!grepl("/^[A-CEGHJ-PR-TW-Z]{1}[A-CEGHJ-NPR-TW-Z]{1}[0-9]{6}[A-D]{1}$/i", DEP_Programmes$NiNo)) %>%
  count(Programme)

有什么建议吗?拜托,谢谢。

2 个答案:

答案 0 :(得分:1)

传递给grepl的正则表达式不使用任何定界符,并且如果您希望不区分大小写,请使用ignore.case选项而不是/i

DEP_Programmes %>% 
    filter(!grepl("^[A-CEGHJ-PR-TW-Z]{1}[A-CEGHJ-NPR-TW-Z]{1}[0-9]{6}[A-D]{1}$", NiNo, ignore.case=TRUE)) %>%
    count(Programme)

注意:您当前的正则表达式看起来很像PHP或JavaScript。

答案 1 :(得分:1)

摘自Wikipedia:

  

[国民保险]号的格式为两个前缀字母,   六位数字和一个后缀字母。 [...]前两个字母都不能为D,F,I,Q,U   或V。第二个字母也不能为O。前缀BG,GB,NK,KN,   未分配TN,NT和ZZ。 [...]后缀字母是A,   B,C或D   (source)。

因此,您发现的正则表达式几乎正确,但是应该删除前导和尾随字符。一点测试:

regex <- "^[A-CEGHJ-PR-TW-Z]{1}[A-CEGHJ-NPR-TW-Z]{1}[0-9]{6}[A-D]{1}$"

test <- c("AB123456A", "******69B", "cms1234", "BCN8888855555",
          "AB 123456 A", NA, "QQ123456C")
grepl(regex, test)
# [1]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE

检查this cheatsheet以供参考。

在原始代码中,该代码应如下所示:

DEP_Programmes %>% 
  filter(grepl("^[A-CEGHJ-PR-TW-Z]{1}[A-CEGHJ-NPR-TW-Z]{1}[0-9]{6}[A-D]{1}$", NiNo)) %>% # omit DEP_Programmes$ inside dplyr pipe
  count(Programme)

请注意,在过滤器中,将保留TRUE值,并删除FALSE值。通过添加前导!,您可以反转选择,这意味着您的TRUE值将被删除(据我了解,您不需要)。这就是为什么您的原始代码没有被删除的原因。由于正则表达式不是正则表达式的惯用语,而是其他某种语言,因此所有字符串均为FALSE。反过来,一切都得以保留。