str_将A1-A9替换为A01-A09等
您好,我的数据中有以下字符串,希望将A1-A9替换为A01-A09,将B1-B9替换为B01-B09,但保留数字str_将A1-A9替换为A01-A09等,r,regex,dataframe,str-replace,R,Regex,Dataframe,Str Replace,您好,我的数据中有以下字符串,希望将A1-A9替换为A01-A09,将B1-B9替换为B01-B09,但保留数字=10 rep_data=data.frame(Str= c("A1B10", "A2B3", "A11B1", "A5B10")) Str 1 A1B10 2 A2B3 3 A11B1 4 A5B10 有一个类似的帖子,但我的问题是有点不同!在这里还没有看到类似的例子 如果你知道解决办法,我会很高兴的 预期产量 Str 1 A01B10 2 A02B03 3 A11B0
=10
rep_data=data.frame(Str= c("A1B10", "A2B3", "A11B1", "A5B10"))
Str
1 A1B10
2 A2B3
3 A11B1
4 A5B10
有一个类似的帖子,但我的问题是有点不同!在这里还没有看到类似的例子
如果你知道解决办法,我会很高兴的
预期产量
Str
1 A01B10
2 A02B03
3 A11B01
4 A05B10
像这样的怎么样
num_pad <- function(x) {
x <- as.character(x)
mm <- gregexpr("\\d+|\\D+",x)
parts <- regmatches(x, mm)
pad_number <- function(x) {
nn<-suppressWarnings(as.numeric(x))
x[!is.na(nn)] <- sprintf("%02d", nn[!is.na(nn)])
x
}
parts <- lapply(parts, pad_number)
sapply(parts, paste0, collapse="")
}
num_pad(rep_data$Str)
# [1] "A01B10" "A02B03" "A11B01" "A05B10"
num\u pad我认为这应该能满足您的需求:
gsub("(?<![0-9])([0-9])(?![0-9])", "0\\1", rep_data$Str, perl = TRUE)
#[1] "A01B10" "A02B03" "A11B01" "A05B10"
gsub((?未彻底检查
x = c("A1B10", "A2B3", "A11B1", "A5B10")
sapply(strsplit(x, ""), function(s){
paste(sapply(split(s, cumsum(s %in% LETTERS)), function(a){
if(length(a) == 2){
a[2] = paste0(0, a[2])
}
paste(a, collapse = "")
}), collapse = "")
})
#[1] "A01B10" "A02B03" "A11B01" "A05B10"
来自tidyverse
和stringr
的解决方案
library(tidyverse)
library(stringr)
rep_data2 <- rep_data %>%
extract(Str, into = c("L1", "N1", "L2", "N2"), regex = "(A)(\\d+)(B)(\\d+)") %>%
mutate_at(vars(starts_with("N")), funs(str_pad(., width = 2, pad = "0"))) %>%
unite(Str, everything(), sep = "")
rep_data2
Str
1 A01B10
2 A02B03
3 A11B01
4 A05B10
库(tidyverse)
图书馆(stringr)
代表数据2%
提取(Str,into=c(“L1”、“N1”、“L2”、“N2”),regex=“(A)(\\d+)(B)(\\d+)”)%>%
在(vars(以“N”开头)、funs(str_pad(,width=2,pad=“0”)))%处突变%>%
联合(Str,everything(),sep=“”)
代表数据2
Str
1 A01B10
2 A02B03
3 A11B01
4 A05B10
这是我能想到的最简洁整洁的解决方案:
library(tidyverse)
library(stringr)
rep_data %>%
mutate(
num_1 = str_match(Str, "A([0-9]+)")[, 2],
num_2 = str_match(Str, "B([0-9]+)")[, 2],
num_1 = str_pad(num_1, width = 2, side = "left", pad = "0"),
num_2 = str_pad(num_2, width = 2, side = "left", pad = "0"),
Str = str_c("A", num_1, "B", num_2)
) %>%
select(- num_1, - num_2)
这里有一个选项带有gsubfn
library(gsubfn)
gsubfn("(\\d+)", ~sprintf("%02d", as.numeric(x)), as.character(rep_data$Str))
#[1] "A01B10" "A02B03" "A11B01" "A05B10"
有点类似于@Mike的答案,但此解决方案使用了一个积极的前瞻:
gsub("(\\D)(?=\\d(\\D|\\b))", "\\10", rep_data$Str, perl = TRUE)
# [1] "A01B10" "A02B03" "A11B01" "A05B10"
使用tidyverse
:
library(dplyr)
library(stringr)
rep_data %>%
mutate(Str = str_replace_all(Str, "(\\D)(?=\\d(\\D|\\b))", "\\10"))
# Str
# 1 A01B10
# 2 A02B03
# 3 A11B01
# 4 A05B10
此正则表达式匹配后面跟一个数字、另一个非数字或单词边界的所有非数字。\\10
很有欺骗性,因为它看起来像是用第十个捕获组替换匹配。相反,它用第一个捕获组加上后面的零替换匹配。这是一个重要要求吗要使用tidyverse?不一定!中间([0-9])是做什么的?它匹配一个数字。中间([0-9])周围的那些匹配非数字