gsub:仅在两个 digits/letters 之间保留给定字符

gsub: Keep a given character only if between two digits/letters

我有一个地址列表,我想将其分成两个数组:

  1. 地址行(在两个字母之间保留特殊字符,例如“-” - c.f。text.2
  2. 门牌号(两位数之间保留“-”等特殊字符)

这是一个例子:

text.1 <- "CALLE COMPOSITOR LEHMBERG RUIZ 19-21"
text.2 <- "CALLE COMPOSITOR LEHMBERG-RUIZ 19-21"

为了提取门牌号,我尝试使用 gsub("[^0-9\-]", "", x),它适用于 text.1,但不如 text.2 所需:

> gsub("[^0-9\-]", "", text.1)
[1] "19-21"
> gsub("[^0-9\-]", "", text.2)
[1] "-19-21"

为了提取地址行,我使用 gsub("[0-9]", "", x) 产生了类似的问题。

我可以用下面的代码绕过这个问题:

ifelse( substr( gsub("[^0-9\-]", "", x ), 1, 1 ) == "-" , 
        substr( gsub("[^0-9\-]", "", x), 2, nchar( gsub("[^0-9\-]", "", x) ) 
           )
        , gsub("[^0-9\-]", "", x)
      )

x = text.1x = text.2 都产生 "19-21"。但是,可以看出它不是很优雅。

我的问题是是否有 "elegant" 方法来解决这个问题(例如,以更聪明的方式使用 gsub)?

我建议您使用 str_extract 而不是 gsub。你可以按如下方式:

library(stringr)
str_extract(text.1,"[0-9]{1,3}\-[0-9]{1,3}")
[1] "19-21"
str_extract(text.2,"[0-9]{1,3}\-[0-9]{1,3}")
[1] "19-21"

str_extract(text.1,"[^0-9][A-Z\-\s]+")
[1] "CALLE COMPOSITOR LEHMBERG RUIZ "
str_extract(text.2,"[^0-9][A-Z\-\s]+")
[1] "CALLE COMPOSITOR LEHMBERG-RUIZ "

我们可以使用正则表达式 SKIP 当模式为真时删除所有其他字符

gsub("(\d+)-(\d+)(*SKIP)(*F)|.", "", text.1, perl = TRUE)
#[1] "19-21"
gsub("(\d+)-(\d+)(*SKIP)(*F)|.", "", text.2, perl = TRUE)
#[1] "19-21"