如何仅在第一个数字上拆分字符串

How to split a string on first number only

所以我有一个包含街道地址的数据集,它们的格式非常不同。例如:

d <- c("street1234", "Street 423", "Long Street 12-14", "Road 18A", "Road 12 - 15", "Road 1/2")

由此我想创建两列。 1. X:街道地址和 2. Y:数字+后面的所有内容。像这样:

X           Y
Street      1234
Street      423
Long Street 12-14
Road        18A
Road        12 - 15
Road        1/2

到目前为止,我已经尝试过 strsplit 并在此处关注了一些类似的问题,例如:strsplit(d, split = "(?<=[a-zA-Z])(?=[0-9])", perl = T))。我似乎找不到正确的正则表达式。

非常感谢任何帮助。提前致谢!

字母和数字之间可能有空格,因此在环视之间添加 \s*(零个或多个空格符号):

> strsplit(d, split = "(?<=[a-zA-Z])\s*(?=[0-9])", perl = TRUE)
[[1]]
[1] "street" "1234"  

[[2]]
[1] "Street" "423"   

[[3]]
[1] "Long Street" "12-14"      

[[4]]
[1] "Road" "18A" 

[[5]]
[1] "Road"    "12 - 15"

[[6]]
[1] "Road" "1/2" 

如果您想基于此创建列,您可以利用 tidyr 包中的 separate :

> library(tidyr)
> separate(data.frame(A = d), col = "A" , into = c("X", "Y"), sep = "(?<=[a-zA-Z])\s*(?=[0-9])")
            X       Y
1      street    1234
2      Street     423
3 Long Street   12-14
4        Road     18A
5        Road 12 - 15
6        Road     1/2

A non-regex 方法使用 stringr 中的 str_locate 来定位字符串中的第一个数字,然后根据该位置进行拆分,即

library(stringr)

ind <- str_locate(d, '[0-9]+')[,1]
setNames(data.frame(do.call(rbind, Map(function(x, y) 
          trimws(substring(x, seq(1, nchar(x), y-1), seq(y-1, nchar(x), nchar(x)-y+1))), 
                                                             d, ind)))[,1:2]), c('X', 'Y'))

#            X       Y
#1      street    1234
#2      Street     423
#3 Long Street   12-14
#4        Road     18A
#5        Road 12 - 15
#6        Road     1/2

注意 您收到一个(无害的)警告,这是 "Road 12 - 15" 字符串拆分的结果,给出 [1] "Road" "12 - 15" ""

这也有效:

do.call(rbind,strsplit(sub('([[:alpha:]]+)\s*([[:digit:]]+)', '\1$\2', d), split='\$'))
#     [,1]          [,2]     
#[1,] "street"      "1234"   
#[2,] "Street"      "423"    
#[3,] "Long Street" "12-14"  
#[4,] "Road"        "18A"    
#[5,] "Road"        "12 - 15"
#[6,] "Road"        "1/2"    

我们可以使用 read.csvbase R

中的 sub
read.csv(text=sub("^([A-Za-z ]+)\s*([0-9]+.*)", "\1,\2", d), 
        header=FALSE, col.names = c("X", "Y"), stringsAsFactors=FALSE)
#             X       Y
#1       street    1234
#2      Street      423
#3 Long Street    12-14
#4        Road      18A
#5        Road  12 - 15
#6        Road      1/2