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?
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
Here is a stringr
one-liner as well,
library(stringr)
word(a[!str_detect(a, '^MS')], 1, sep = fixed('.'))
#[1] "AT2G26340" "AT2G26355"
Code
a <- a[!grepl("^MS", a)]
gsub("\\.[0-9]$", "", a)
# [1] "AT2G26340" "AT2G26355"
Explanation
regex
to filter out all elements which start with MS
regex
again to replace the dot and the last digit from the remaining elementsAs 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~
Think of them as filenames and drop the extension:
tools::file_path_sans_ext(a[ !grepl("^MS", a) ])
# [1] "AT2G26340" "AT2G26355"
I don't see a combination of sub()
and startsWith()
, so
sub(".{2}$", "", a[!startsWith(a, "MS")])
# [1] "AT2G26340" "AT2G26355"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With