Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

str_replace A1-A9 to A01-A09 and so on

Hi I have a following strings in my data and would like to replace A1-A9 to A01-A09 and B1-B9 to B01-B09 but keep the numbers >=10.

rep_data=data.frame(Str= c("A1B10", "A2B3", "A11B1", "A5B10"))

    Str
1 A1B10
2  A2B3
3 A11B1
4 A5B10

There is a similar post here but my problem is little bit different! and haven't seen similar example in here str_replace.

Will be very glad if you know the solution.

expected output

Str
1 A01B10
2 A02B03
3 A11B01
4 A05B10
like image 784
Alexander Avatar asked Oct 24 '17 19:10

Alexander


2 Answers

I think this should get you what you want:

gsub("(?<![0-9])([0-9])(?![0-9])", "0\\1", rep_data$Str, perl = TRUE)
#[1] "A01B10" "A02B03" "A11B01" "A05B10"

It uses PCRE lookahead's/lookbehind's to match a 1 digit number and then pastes a "0" onto it.

like image 71
Mike H. Avatar answered Nov 01 '22 07:11

Mike H.


How about something like this

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"

Basically we use regular expressions to split the strings up into digit and non-digit groups. We then find those values that look like numbers and use sprintf() to zero-pad them to 2 characters. Then we insert the padded values into the vector and paste everything back together.

like image 3
MrFlick Avatar answered Nov 01 '22 09:11

MrFlick