How to extract numbers from a mixed string in R

Viewed 118
df
   Chromosome aaChange
1          16 p.E548fs
2          16   p.S64X
3          16   p.P23H
4          16   p.G18V
5          16  p.L251S

I'm trying to extract numbers from aaChange, namely 584, 64, 23, 18, 251. I've run the code below:

    df <- tidyr::extract(df, aaChange, into = 'Protein_position', ".*(\\d+).*", 
                         remove = F, convert = T)

But the output is:

df
   Chromosome aaChange Protein_position
1          16 p.E548fs                8
2          16   p.S64X                4
3          16   p.P23H                3
4          16   p.G18V                8
5          16  p.L251S                1

I dont know how to modify the regex. Any help is appreciated.

5 Answers

If the number parts of aaChange are always going to be grouped together you can use something very simple:

tidyr::extract(df, aaChange, into = 'Protein_position', "(\\d+)", remove = F, convert = T)
#>   Chromosome aaChange Protein_position
#> 1         16 p.E548fs              548
#> 2         16   p.S64X               64
#> 3         16   p.P23H               23
#> 4         16   p.G18V               18
#> 5         16  p.L251S              251

You could also do:

df = data.frame(aaChange = c("p.E548fs", "p.S64X", "p.P23H", "p.G18V", "p.L251S"))
df$Protein_position = as.numeric(gsub("\\D", "", df$aaChange))
df
 aaChange Protein_position
1 p.E548fs              548
2   p.S64X               64
3   p.P23H               23
4   p.G18V               18
5  p.L251S              251

Does this work:

library(dplyr)
library(string)
df %>% mutate(Protein_position = str_extract(aaChange, '(?<=p\\.[A-Z])\\d+(?=[A-z]{1,2})'))
  Chromosome aaChange Protein_position
1         16 p.E548fs              548
2         16   p.S64X               64
3         16   p.P23H               23
4         16   p.G18V               18
5         16  p.L251S              251

Data used:

df
  Chromosome aaChange
1         16 p.E548fs
2         16   p.S64X
3         16   p.P23H
4         16   p.G18V
5         16  p.L251S

We can use sub from base R

df$Protein_position <- as.numeric(sub("^\\D+(\\d+).*", "\\1", df$aaChange))
df$Protein_position
#[1] 548  64  23  18 251

We can use regmatches to extract all numbers

transform(
  df,
  Protein_position = as.numeric(unlist(regmatches(aaChange, gregexpr("\\d+", aaChange))))
)

which gives

  Chromosome aaChange Protein_position
1         16 p.E548fs              548
2         16   p.S64X               64
3         16   p.P23H               23
4         16   p.G18V               18
5         16  p.L251S              251
Related