R中的字符串ID格式检查和填充
一些代码的格式为数字除以破折号(例如,社会保险号码的格式通常为“ddd dddd dddd”,其中d代表任何数字;用简短的3-2-4格式表示,代表每个“区块”中的数字数) 我需要输入5-4、4-4或5-3格式的产品代码,然后: (a) 验证它们是否符合这些格式中的任何一种,以及(b)用零填充,以便输出为5-4格式 这里有一个代码可以做到这一点。有更好的方法吗?如何将其矢量化R中的字符串ID格式检查和填充,r,string,input,R,String,Input,一些代码的格式为数字除以破折号(例如,社会保险号码的格式通常为“ddd dddd dddd”,其中d代表任何数字;用简短的3-2-4格式表示,代表每个“区块”中的数字数) 我需要输入5-4、4-4或5-3格式的产品代码,然后: (a) 验证它们是否符合这些格式中的任何一种,以及(b)用零填充,以便输出为5-4格式 这里有一个代码可以做到这一点。有更好的方法吗?如何将其矢量化 library(stringr) as_product_code <- function(x) { # Cle
library(stringr)
as_product_code <- function(x) {
# Clean Product Codes
# Input: 5-4, 5-3, or 4-4 product code.
# Output: 5-4 product code.
chunks <- unlist(strsplit(x, split = "-", fixed = T))
if (length(chunks == 2) & (identical(nchar(chunks), c(5L, 3L)) |
identical(nchar(chunks), c(5L, 4L)) |
identical(nchar(chunks), c(4L, 4L)))) {
output_code<- paste(str_pad(chunks[1], pad = "0", width = 5),
str_pad(chunks[2], pad = "0", width = 4),
sep = "-")
return(output_code)
} else {
warning("Unexpected format. Doing nothing.")
return(x)
}
}
库(stringr)
作为产品,您可以使用正则表达式和stringr
-包。对于不遵循指定模式的条目,这将返回NA
对于正则表达式,请查看
\\d
表示任何数字(0-9),括号{}中的数字表示重复次数(或{min,max}或{exact})。^
表示我正在查看字符串的开头,$
标记结束。因此,我不匹配字符串末尾的ab
test <- c("1234-1234", "12345-123", "12345-1234ab", "12345-1234", "1234-123")
ifelse(str_detect(test, "^(\\d{4,5})-(\\d{4})$|^(\\d{5})-(\\d{3})$"),
str_replace_all(test, c("^(\\d{4})-" = "0\\1-", "-(\\d{3})$" = "-0\\1")),
NA)
[1] "01234-1234" "12345-0123" NA "12345-1234" NA
test您可以使用正则表达式和stringr
-包。对于不遵循指定模式的条目,这将返回NA
对于正则表达式,请查看
\\d
表示任何数字(0-9),括号{}中的数字表示重复次数(或{min,max}或{exact})。^
表示我正在查看字符串的开头,$
标记结束。因此,我不匹配字符串末尾的ab
test <- c("1234-1234", "12345-123", "12345-1234ab", "12345-1234", "1234-123")
ifelse(str_detect(test, "^(\\d{4,5})-(\\d{4})$|^(\\d{5})-(\\d{3})$"),
str_replace_all(test, c("^(\\d{4})-" = "0\\1-", "-(\\d{3})$" = "-0\\1")),
NA)
[1] "01234-1234" "12345-0123" NA "12345-1234" NA
test您可以使用Vectorize
base R函数:
as_product_code <- function(x) {
#your function
}
x <- c('1234-1234','1234-1234')
as_product_code_vec <- Vectorize(as_product_code,'x',USE.NAMES = F)
as_product_code_vec(x)
as\u product\u code您可以使用矢量化
base R函数:
as_product_code <- function(x) {
#your function
}
x <- c('1234-1234','1234-1234')
as_product_code_vec <- Vectorize(as_product_code,'x',USE.NAMES = F)
as_product_code_vec(x)
as_product_code我们实际上可以利用这里的dataframe
结构来获得一些矢量化帮助
# Create reproducible example
set.seed(9025)
d1 = sample(1:5, 1e5, replace=TRUE)
d2 = sample(1:5, 1e5, replace=TRUE)
codes = sapply(1:1e5, function(i) {
c1 = paste0(sample(1:9, d1[i]), collapse='')
c2 = paste0(sample(1:9, d2[i]), collapse='')
paste(c1, c2, sep='-')
})
library(stringr)
library(tidyverse)
# Create our dataframe, separate the product code, pad the values,
# and use vectorized ifelse to "remove" bad product codes.
output = codes %>%
tbl_df() %>%
separate(value, into=c('c1', 'c2'), sep='-', remove=TRUE) %>%
mutate(include = ifelse(nchar(c1) %in% 4:5 &
nchar(c2) %in% 3:4 &
(nchar(c1) + nchar(c2) > 7),
1, 0),
c1 = str_pad(c1, width=5, side='left', pad=0),
c2 = str_pad(c2, width=4, side='right', pad=0),
code = paste(c1, c2, sep='-')) %>%
mutate(code = ifelse(include == 1, code, '')) %>%
pull(code)
head(codes)
[1] "62971-2" "5-51864" "32419-328" "931-8"
[5] "18324-248" "8-628"
head(output)
[1] "" "" "32419-3280"
[4] "" "18324-2480" ""
实际上,我们可以利用这里的dataframe
结构来获得一些矢量化帮助
# Create reproducible example
set.seed(9025)
d1 = sample(1:5, 1e5, replace=TRUE)
d2 = sample(1:5, 1e5, replace=TRUE)
codes = sapply(1:1e5, function(i) {
c1 = paste0(sample(1:9, d1[i]), collapse='')
c2 = paste0(sample(1:9, d2[i]), collapse='')
paste(c1, c2, sep='-')
})
library(stringr)
library(tidyverse)
# Create our dataframe, separate the product code, pad the values,
# and use vectorized ifelse to "remove" bad product codes.
output = codes %>%
tbl_df() %>%
separate(value, into=c('c1', 'c2'), sep='-', remove=TRUE) %>%
mutate(include = ifelse(nchar(c1) %in% 4:5 &
nchar(c2) %in% 3:4 &
(nchar(c1) + nchar(c2) > 7),
1, 0),
c1 = str_pad(c1, width=5, side='left', pad=0),
c2 = str_pad(c2, width=4, side='right', pad=0),
code = paste(c1, c2, sep='-')) %>%
mutate(code = ifelse(include == 1, code, '')) %>%
pull(code)
head(codes)
[1] "62971-2" "5-51864" "32419-328" "931-8"
[5] "18324-248" "8-628"
head(output)
[1] "" "" "32419-3280"
[4] "" "18324-2480" ""
在我看来,这已经相当矢量化了!我只需要删除函数@AntoinePissoort中的库(stringr)
,它不起作用,例如x=c(“1234-1234”,“1234-1234”)
@AntoinePissoort,我已经编辑以反映您的其他建议。谢天谢地,在我看来,这已经相当矢量化了!我只需要删除函数@AntoinePissoort中的库(stringr)
,它不起作用,例如x=c(“1234-1234”,“1234-1234”)
@AntoinePissoort,我已经编辑以反映您的其他建议。感谢伟大的方法。但它通过4-3作为正确的输入。哦,是的,这是真的,我做了一个快速修复。可能有一个更优雅的解决方案来验证输入。在这种情况下,更多可能的组合会变得更混乱,但对于你的问题,它应该起到作用。很好的方法。但它通过4-3作为正确的输入。哦,是的,这是真的,我做了一个快速修复。可能有一个更优雅的解决方案来验证输入。在这种情况下,可能会有更多可能的组合,但对于您的问题,它应该做到这一点。这不会验证输入和PAD错误。例如,“1234-123”变为“01234-1230”。@dzeltzer在验证逻辑方面有点笨拙,但更新的代码包含了您的验证逻辑。@dzeltzer由于某种原因,我今天上午所做的最后更改没有应用到我的编辑中,这将导致不正确的输出。现在的代码应该可以工作了。这不会验证输入,也不会导致错误。例如,“1234-123”变为“01234-1230”。@dzeltzer在验证逻辑方面有点笨拙,但更新的代码包含了您的验证逻辑。@dzeltzer由于某种原因,我今天上午所做的最后更改没有应用到我的编辑中,这将导致不正确的输出。现在的代码应该可以工作。