如何仅在第一个数字上拆分字符串
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.csv
和 base 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
所以我有一个包含街道地址的数据集,它们的格式非常不同。例如:
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.csv
和 base 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