如何为R数据集中带短横线的数值补前导零以匹配XXXXXXXX-XX格式
问题描述
我的数据集包含3类不同格式的值,其中两类带有短横线,示例数据如下:
df=c("20001982-02", "19933626-02", "20024861-6", "29114-1", "20109774-02", "19965663-01", "19992655-01", "20087008-08", "140107", "20032011-09", "139")
需要为所有带短横线的值补充前导零,使其符合XXXXXXXX-XX的格式(短横线前为8位数字、短横线后为2位数字),不带短横线的值保持原样即可,预期输出如下:
df.new =c("20001982-02", "19933626-02", "20024861-06", "00029114-01", "20109774-02", "19965663-01", "19992655-01", "20087008-08", "140107", "20032011-09", "139")
当前编写的sub正则语句仅能完成部分补零需求,仅处理了短横线前已为8位、短横线后为1位的情况,比如29114-1没有被处理为预期的00029114-01,现有代码如下:
sub("^(\\d{8})-(\\d)$", "\\1-0\\2", df) df.new = c("20001982-02", "19933626-02", "20024861-06", "29114-1", "20109774-02", "19965663-01", "19992655-01", "20087008-08", "140107", "20032011-09", "139")
请问如何调整逻辑实现完整的补零需求?
解决方案
原有代码问题排查
当前的正则仅匹配短横线前恰好8位、短横线后恰好1位的字符串,完全没有覆盖短横线前不足8位的场景,因此29114-1这类值不会被匹配处理。
实现代码
Base R 实现(无需加载第三方包)
通过遍历+条件判断+格式化补零实现:
df <- c("20001982-02", "19933626-02", "20024861-6", "29114-1", "20109774-02", "19965663-01", "19992655-01", "20087008-08", "140107", "20032011-09", "139") df.new <- sapply(df, function(x) { # 不带短横线的直接返回 if (!grepl("-", x)) return(x) # 拆分短横线前后两部分 parts <- strsplit(x, "-")[[1]] # 前半部分补前导零到8位,后半部分补前导零到2位 part1 <- sprintf("%08d", as.integer(parts[1])) part2 <- sprintf("%02d", as.integer(parts[2])) # 拼接返回 paste0(part1, "-", part2) }, USE.NAMES = FALSE)
stringr 实现(更简洁的正则写法)
如果习惯用tidyverse生态,可以用str_replace_all的函数式替换能力实现:
library(stringr) df.new <- str_replace_all(df, "^(\\d+)-(\\d+)$", function(match, g1, g2) { paste0(sprintf("%08d", as.integer(g1)), "-", sprintf("%02d", as.integer(g2))) })
两种实现输出的结果和预期完全一致。
内容的提问来源于stack exchange,提问作者Andres Mora
相关产品推荐
相关产品推荐

