R - 在邮政编码字符串中插入可变数量的空格
R - Inserting variable number of spaces into postcode string
我有一组英国邮政编码需要重新格式化。它们由一个 incode 和一个 outcode 组成,其中 incode 的形式为 'number letter letter' 例如2DB 和 outcode 是 2 到 4 个字母和数字的组合,例如NW1 或 SW10 或 EC1A
目前 incode 和 outcode 之间有一个 space,但我需要重新格式化它们,以便完整的邮政编码长度为 7 个字符,例如:('-' 代表 space)
- NW1-2DB -> NW1-2DB(1 space outcode 和 incode 之间)
- SW10-9NH -> SW109NH (0 spaces)
- E1-6QL -> E1--6QL (2 spaces)
数据:
df <- data.frame("postcode"=c("NW1 2DB","SW10 9NH","E1 6QL"))
df
# postcode
# 1 NW1 2DB
# 2 SW10 9NH
# 3 E1 6QL
我写了一个正则表达式字符串来分隔输出代码和输入代码,但找不到在它们之间添加可变数量的 space 的方法(这个例子只创建了两个 space s 在 outcode 和 incode 之间)。
require(dplyr)
df <- df %>% mutate(postcode_2sp = gsub('?(\S+)\s*?(\d\w{2})$','\1 \2', postcode)
为了解决这个问题,我尝试使用 mutate()
、nchar()
和 rep()
:
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=paste0(outcode,
paste0(rep(" ",4-out_length),collapse=""),
incode))
但出现此错误:
Error: invalid 'times' argument
没有创建邮政编码 7 的最后一步,df 如下所示:
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<-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=paste0(outcode,
paste0(rep(" ",4),collapse=""),
incode))
df
# postcode outcode incode out_length postcode7
# 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
包中的 str_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
使用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`))
我喜欢上面发布的 separate
版本,但它要求邮政编码全部由空格分隔。根据我的经验,通常情况并非如此。
df%>%mutate(Postcode7=paste0(format(gsub('\s.*$','',postcode),justify='left'),
format(gsub('^\S+\s','',postcode),justify='right')))
我有一组英国邮政编码需要重新格式化。它们由一个 incode 和一个 outcode 组成,其中 incode 的形式为 'number letter letter' 例如2DB 和 outcode 是 2 到 4 个字母和数字的组合,例如NW1 或 SW10 或 EC1A
目前 incode 和 outcode 之间有一个 space,但我需要重新格式化它们,以便完整的邮政编码长度为 7 个字符,例如:('-' 代表 space)
- NW1-2DB -> NW1-2DB(1 space outcode 和 incode 之间)
- SW10-9NH -> SW109NH (0 spaces)
- E1-6QL -> E1--6QL (2 spaces)
数据:
df <- data.frame("postcode"=c("NW1 2DB","SW10 9NH","E1 6QL"))
df
# postcode
# 1 NW1 2DB
# 2 SW10 9NH
# 3 E1 6QL
我写了一个正则表达式字符串来分隔输出代码和输入代码,但找不到在它们之间添加可变数量的 space 的方法(这个例子只创建了两个 space s 在 outcode 和 incode 之间)。
require(dplyr)
df <- df %>% mutate(postcode_2sp = gsub('?(\S+)\s*?(\d\w{2})$','\1 \2', postcode)
为了解决这个问题,我尝试使用 mutate()
、nchar()
和 rep()
:
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=paste0(outcode,
paste0(rep(" ",4-out_length),collapse=""),
incode))
但出现此错误:
Error: invalid 'times' argument
没有创建邮政编码 7 的最后一步,df 如下所示:
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<-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=paste0(outcode,
paste0(rep(" ",4),collapse=""),
incode))
df
# postcode outcode incode out_length postcode7
# 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
包中的 str_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
使用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`))
我喜欢上面发布的 separate
版本,但它要求邮政编码全部由空格分隔。根据我的经验,通常情况并非如此。
df%>%mutate(Postcode7=paste0(format(gsub('\s.*$','',postcode),justify='left'),
format(gsub('^\S+\s','',postcode),justify='right')))