Regex R-在邮政编码字符串中插入可变数量的空格
我有一套英国邮政编码,需要重新格式化。它们由incode和outcode组成,其中incode的形式为“数字字母字母”,例如2DB,outcode是2到4个字母和数字的组合,例如NW1或SW10或EC1A 目前,incode和outcode之间有一个空格,但我需要重新格式化这些空格,以便完整的邮政编码为7个字符长,例如:(“-”代表空格)Regex R-在邮政编码字符串中插入可变数量的空格,regex,r,dplyr,postal-code,Regex,R,Dplyr,Postal Code,我有一套英国邮政编码,需要重新格式化。它们由incode和outcode组成,其中incode的形式为“数字字母字母”,例如2DB,outcode是2到4个字母和数字的组合,例如NW1或SW10或EC1A 目前,incode和outcode之间有一个空格,但我需要重新格式化这些空格,以便完整的邮政编码为7个字符长,例如:(“-”代表空格) NW1-2DB->NW1-2DB(输出代码和输入代码之间有1个空格) SW10-9NH->SW109NH(0个空间) E1-6QL->E1--6QL(2个空
- NW1-2DB->NW1-2DB(输出代码和输入代码之间有1个空格)
- SW10-9NH->SW109NH(0个空间)
- E1-6QL->E1--6QL(2个空格)
df
# postcode outcode incode out_length
# 1 NW1 2DB NW1 2DB 3
# 2 SW10 9NH SW10 9NH 4
# 3 E1 6QL E1 6QL 2
如果我将rep'times'参数设置为常量,代码将按预期运行(但不执行我需要它执行的操作!)
df%
突变(outcode=gsub('?(\\S+\\S*\\d\\w{2}$','\\1',邮政编码),
incode=gsub('\\S+\\S*?(\\d\\w{2})$','\\1',邮政编码))%>%
突变(输出长度=nchar(输出代码))%>%
突变(邮政编码7=粘贴0(输出代码,
粘贴0(rep(“,4),collapse=”“),
国际编码)
df
#邮政编码输出代码输入代码输出长度邮政编码7
#1 NW1 2DB NW1 2DB 3 NW1 2DB
#2 SW10 9NH SW10 9NH 4 SW10 9NH
#3 E1 6QL E1 6QL 2 E1 6QL
有没有办法让rep()
接受一列作为mutate中的times参数?或者我应该考虑一种完全不同的方法
编辑:我刚刚意识到,我可以对输出代码中的每一个2个字符、3个字符或4个字符使用
if
语句,但这感觉不是很优雅。看看stringr
包中的stru\u-pad
方法,它适合您的情况:
library(stringr)
df<-df %>%
mutate(outcode=gsub('?(\\S+)\\s*\\d\\w{2}$','\\1',postcode),
incode=gsub('\\S+\\s*?(\\d\\w{2})$','\\1',postcode)) %>%
mutate(out_length=nchar(outcode)) %>%
mutate(postcode7 = paste(outcode, str_pad(incode, 7-out_length), sep = ""))
df
# postcode outcode incode out_length postcode7
# 1 NW1 2DB NW1 2DB 3 NW1 2DB
# 2 SW10 9NH SW10 9NH 4 SW109NH
# 3 E1 6QL E1 6QL 2 E1 6QL
库(stringr)
df%
突变(outcode=gsub('?(\\S+\\S*\\d\\w{2}$','\\1',邮政编码),
incode=gsub('\\S+\\S*?(\\d\\w{2})$','\\1',邮政编码))%>%
突变(输出长度=nchar(输出代码))%>%
变异(邮政编码7=粘贴(输出代码,字符串填充(输入代码,7-out长度),sep=”“)
df
#邮政编码输出代码输入代码输出长度邮政编码7
#1 NW1 2DB NW1 2DB 3 NW1 2DB
#2 SW10 9NH SW10 9NH 4 SW109NH
#3 E1 6QL E1 6QL 2 E1 6QL
使用str_pad和分离:
library(dplyr)
library(tidyr)
library(stringr)
df %>%
separate(postcode, into = c("incode", "outcode"), remove = FALSE) %>%
mutate(
postcode8 = paste0(incode,
str_pad(outcode,
8 - nchar(incode), side = "left", pad = " ")))
# postcode incode outcode postcode8
# 1 NW1 2DB NW1 2DB NW1 2DB
# 2 SW10 9NH SW10 9NH SW10 9NH
# 3 E1 6QL E1 6QL E1 6QL
另一种解决方案是,使用
sprintf
格式化输出,使用tidyr::extract
进行匹配。这样做的优点是大大简化了填充的模式和代码:
df %>%
extract(postcode, into = c('out', 'in'), '(\\S{2,4})\\s*(\\d\\w\\w)') %>%
mutate(postcode = sprintf('% -4s%s', out, `in`))
我确实喜欢上面发布的
分离版
,但它要求邮政编码都用空格分隔。根据我的经验,通常情况并非如此。您是否必须使用正则表达式来拆分邮政编码?strsplit
有什么问题?@Psidom默认情况下,strsplit
也使用正则表达式-但问题是strsplit
需要一些东西来拆分。如果你查看OP的正则表达式,你会发现中间的空间在输入中完全是可选的。你是正确的,<代码> StruSts/Code >,只要在代码和代码之间有一个空间(如我所指定的),但是Konrad是正确的,因为邮政编码不总是这样格式化的。我的问题太具体了,这不好。@KonradRudolph OK。我正在读OP的声明,因为目前在incode和outcode之间有一个空格。没有仔细查看正则表达式。这是有道理的。该代码通常不起作用,它要求(a)至少有一个空格分隔邮政编码组,以及(b)数据框至少包含一个已正确格式化的邮政编码;否则,理由就行不通了。
df%>%mutate(Postcode7=paste0(format(gsub('\\s.*$','',postcode),justify='left'),
format(gsub('^\\S+\\s','',postcode),justify='right')))
library(stringr)
df<-df %>%
mutate(outcode=gsub('?(\\S+)\\s*\\d\\w{2}$','\\1',postcode),
incode=gsub('\\S+\\s*?(\\d\\w{2})$','\\1',postcode)) %>%
mutate(out_length=nchar(outcode)) %>%
mutate(postcode7 = paste(outcode, str_pad(incode, 7-out_length), sep = ""))
df
# postcode outcode incode out_length postcode7
# 1 NW1 2DB NW1 2DB 3 NW1 2DB
# 2 SW10 9NH SW10 9NH 4 SW109NH
# 3 E1 6QL E1 6QL 2 E1 6QL
library(dplyr)
library(tidyr)
library(stringr)
df %>%
separate(postcode, into = c("incode", "outcode"), remove = FALSE) %>%
mutate(
postcode8 = paste0(incode,
str_pad(outcode,
8 - nchar(incode), side = "left", pad = " ")))
# postcode incode outcode postcode8
# 1 NW1 2DB NW1 2DB NW1 2DB
# 2 SW10 9NH SW10 9NH SW10 9NH
# 3 E1 6QL E1 6QL E1 6QL
df %>%
extract(postcode, into = c('out', 'in'), '(\\S{2,4})\\s*(\\d\\w\\w)') %>%
mutate(postcode = sprintf('% -4s%s', out, `in`))
df%>%mutate(Postcode7=paste0(format(gsub('\\s.*$','',postcode),justify='left'),
format(gsub('^\\S+\\s','',postcode),justify='right')))