首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >R中的字符串ID格式检查和填充

R中的字符串ID格式检查和填充
EN

Stack Overflow用户
提问于 2017-10-16 11:05:43
回答 3查看 94关注 0票数 1

有些代码被格式化为数字除以破折号(例如,社会保障号码通常被格式化为“dddd”,其中d代表任何数字;用短3-2-4格式表示,代表每个“块”中的数字数)。

我需要输入5-4,4-4或5-3格式的产品代码,然后:(a)验证它们是否符合任何这些格式,(b)用零填充,以便输出采用5-4格式。

这里有一个代码可以做到这一点。有更好的方法吗?如何将其矢量化?

代码语言:javascript
运行
复制
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)
  }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-10-16 11:23:07

您可以使用正则表达式和stringr-package。这将返回不符合指定模式的条目的NA。

对于正则表达式,请看一下备忘单

\\d代表任何数字(0-9),括号中的数字{}表示重复次数( {min,max}或{ for })。^意味着,我正在查看字符串的开头,而$则表示结束。因此,我不匹配的字符串与ab在末尾。

代码语言:javascript
运行
复制
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 
票数 3
EN

Stack Overflow用户

发布于 2017-10-16 11:32:57

我们实际上可以利用这里的dataframe结构获得一些矢量化帮助。

代码语言:javascript
运行
复制
# 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" "" 
票数 2
EN

Stack Overflow用户

发布于 2017-10-16 11:31:37

您可以使用Vectorize基R函数:

代码语言:javascript
运行
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46768850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档