Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove certain items from a vector?

Tags:

regex

r

vector

Example vector (gene transcript ids):

a <- c('MSTRG.7176.1', 'MSTRG.7176.2', 'AT2G26340.2', 'AT2G26355.1')

This is subset of a long vector, how can I remove item begin with 'MS', then cut off the end 2 digit of left items?

like image 328
Donghui HU Avatar asked Mar 14 '19 07:03

Donghui HU


6 Answers

If we want to avoid regex completely as @sindri_baldur mentions we can use

string <- a[!startsWith(a, "MS")]
substr(string, 1, nchar(string) - 2)

Or with grep and substr

string <- grep('^MS',a, invert = TRUE, value = TRUE)
substr(string, 1, nchar(string) - 2)
#[1] "AT2G26340" "AT2G26355"

Since we have quite a few new answers adding benchmark including all of them with a vector of length 400k.

a <- c('MSTRG.7176.1', 'MSTRG.7176.2', 'AT2G26340.2', 'AT2G26355.1')
a <- rep(a, 100000)

library(microbenchmark)

microbenchmark(
ronak1 = {string <- a[!startsWith(a, "MS")];substr(string, 1, nchar(string) - 2)}, 
ronak2 = {string <- grep('^MS',a, invert = TRUE, value = TRUE);substr(string, 1, nchar(string) - 2)}, 
sotos = {word(a[!str_detect(a, '^MS')], 1, sep = fixed('.'))}, 
thothal = {b1 <- a[!grepl("^MS", a)];gsub("\\.[0-9]$", "", b1)}, 
zx8754 = tools::file_path_sans_ext(a[ !grepl("^MS", a) ]), 
tmfmnk = dirname(chartr(".", "/", a[!grepl("^MS", a)])), 
NelSonGon = {b<-stringi::stri_replace_all(stringi::stri_sub(a,1,-3),regex="^M.*","");b[grepl('\\w+',b)]}
)


#Unit: milliseconds
#      expr        min         lq       mean     median         uq       max neval
#    ronak1   34.75928   38.58217   45.63393   40.32845   44.24355  225.2581   100
#    ronak2   94.10687   96.72758  110.83819   99.26914  105.98822  938.2969   100
#     sotos 1926.21112 2500.27209 2852.43240 2861.61699 3173.10420 4478.7890   100
#   thothal  155.95328  160.62800  169.02275  164.46494  169.32770  218.5033   100
#    zx8754  172.96970  179.03618  186.12374  183.96887  188.06251  234.1895   100
#    tmfmnk  189.29085  195.14593  208.89245  199.47172  204.40604  547.7497   100
# NelSonGon  186.54426  198.29856  226.19221  206.54542  217.92970  948.2535   100
like image 91
Ronak Shah Avatar answered Nov 10 '22 05:11

Ronak Shah


Here is a stringr one-liner as well,

library(stringr)

word(a[!str_detect(a, '^MS')], 1, sep = fixed('.'))
#[1] "AT2G26340" "AT2G26355"
like image 29
Sotos Avatar answered Nov 10 '22 04:11

Sotos


Code

a <- a[!grepl("^MS", a)]
gsub("\\.[0-9]$", "", a)
# [1] "AT2G26340" "AT2G26355"

Explanation

  1. Use regex to filter out all elements which start with MS
  2. Use regex again to replace the dot and the last digit from the remaining elements
like image 41
thothal Avatar answered Nov 10 '22 05:11

thothal


As there are about 200K transcripts in human, here is the benchmark:

a <- c('MSTRG.7176.1', 'MSTRG.7176.2', 'AT2G26340.2', 'AT2G26355.1')
a <- rep(a, 25000)

library(stringr)

bench::mark(
  x1 = {
    string <- grep('^MS',a, invert = TRUE, value = TRUE)
    substr(string, 1, nchar(string) - 2) },
  x2 = {
    string <- a[!startsWith(a, "MS")]
    substr(string, 1, nchar(string) - 2)},
  x3 = {
    word(a[!str_detect(a, '^MS')], 1, sep = fixed('.'))  
  },
  x4 = {
    gsub("\\.[0-9]$", "", a[ !grepl("^MS", a) ])},
  x5 = {
    tools::file_path_sans_ext(a[ !grepl("^MS", a) ])  
  }
  )

# A tibble: 5 x 14
# expression      min     mean  median     max `itr/sec` mem_alloc  n_gc n_itr total_time result memory  time  gc   
# <chr>      <bch:tm> <bch:tm> <bch:t> <bch:t>     <dbl> <bch:byt> <dbl> <int>   <bch:tm> <list> <list>  <lis> <lis>
# x1           20.3ms   21.3ms    21ms  28.1ms     46.9     1.91MB     1    24      512ms <chr ~ <Rprof~ <bch~ <tib~
# x2           11.7ms   12.6ms  12.3ms  17.8ms     79.3     2.86MB     3    40      505ms <chr ~ <Rprof~ <bch~ <tib~
# x3          668.5ms  668.5ms 668.5ms 668.5ms      1.50   10.54MB     9     1      668ms <chr ~ <Rprof~ <bch~ <tib~
# x4           23.8ms   24.6ms  24.1ms  32.2ms     40.7      2.1MB     1    21      516ms <chr ~ <Rprof~ <bch~ <tib~
# x5           33.8ms   35.2ms  34.7ms  40.9ms     28.4      2.1MB     1    15      528ms <chr ~ <Rprof~ <bch~ <tib~
like image 27
zx8754 Avatar answered Nov 10 '22 05:11

zx8754


Think of them as filenames and drop the extension:

tools::file_path_sans_ext(a[ !grepl("^MS", a) ])
# [1] "AT2G26340" "AT2G26355"
like image 26
zx8754 Avatar answered Nov 10 '22 04:11

zx8754


I don't see a combination of sub() and startsWith(), so

sub(".{2}$", "", a[!startsWith(a, "MS")])
# [1] "AT2G26340" "AT2G26355"
like image 31
Rich Scriven Avatar answered Nov 10 '22 03:11

Rich Scriven