CodingButStillAlive CodingButStillAlive - 15 days ago 5
R Question

How to use sub in R with numeric operations on the matches?

Let's say I want to change the string

X0_Y1_Z2
into
X0_Y1_Z1
, i.e. to decrease the last number by one. I tried it by the following statement in R, which doesn't work:

sub("(\\S+_\\S+_)\\S(\\d)", paste0("\\1", as.numeric("\\2")-1), "X0_Y1_Z2", perl=T)


How can I do it?

Answer

If you always have the string in this same format, and you only have 1 last digit to decrement, use a simple substring:

> paste0(substring(s, 1, nchar(s)-1), as.numeric(substring(s, nchar(s))) - 1)
> [1] "X0_Y1_Z1"

In order to match the last digit chunk in a string, use [0-9]+$ regex. To increase the value, use gsubfn package. See an example code:

> library(gsubfn)
> s <- "X0_Y1_Z2"
> gsubfn('[0-9]+$', ~ as.numeric(x)-1, s)
[1] "X0_Y1_Z1"

If you need to validate the string the way you did, use more groups and the anchors ^ and $ will require the whole string to match the pattern (a "full string match"):

> p <- "^(\\S+_\\S+_\\S)(\\d+)$"
> gsubfn(p, function(x1,x2) paste0(x1, as.numeric(x2)-1), s)
[1] "X0_Y1_Z1"