有些代码被格式化为数字除以破折号(例如,社会保障号码通常被格式化为“dddd”,其中d代表任何数字;用短3-2-4格式表示,代表每个“块”中的数字数)。
我需要输入5-4,4-4或5-3格式的产品代码,然后:(a)验证它们是否符合任何这些格式,(b)用零填充,以便输出采用5-4格式。
这里有一个代码可以做到这一点。有更好的方法吗?如何将其矢量化?
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)
}
}
发布于 2017-10-16 11:23:07
您可以使用正则表达式和stringr
-package。这将返回不符合指定模式的条目的NA。
对于正则表达式,请看一下备忘单。
\\d
代表任何数字(0-9),括号中的数字{}表示重复次数( {min,max}或{ for })。^
意味着,我正在查看字符串的开头,而$
则表示结束。因此,我不匹配的字符串与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
发布于 2017-10-16 11:32:57
我们实际上可以利用这里的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" ""
发布于 2017-10-16 11:31:37
您可以使用Vectorize
基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)
https://stackoverflow.com/questions/46768850
复制相似问题