2015-10-11 35 views
1

我有这个矢量myvec。我想在秒后删除所有内容:'并获得结果。如何在nth':'后删除字符串?如何删除R中第n个分隔符后的所有内容?

myvec<- c("chr2:213403244:213403244:G:T:snp","chr7:55240586:55240586:T:G:snp" ,"chr7:55241607:55241607:C:G:snp") 

result 
chr2:213403244 
chr7:55240586 
chr7:55241607 

回答

1

我们可以使用sub。我们匹配一个或多个不是:的字符(^([^:]+),然后是:,然后是一个不是:[^:]+)的字符,将它放在捕获组中,即括号内。我们用替换中的捕获组(\\1)替换。

sub('^([^:]+:[^:]+).*', '\\1', myvec) 
#[1] "chr2:213403244" "chr7:55240586" "chr7:55241607" 

上面的例子发布的作品。对于一般情况下,第n个分隔符后取出,

n <- 2 
pat <- paste0('^([^:]+(?::[^:]+){',n-1,'}).*') 
sub(pat, '\\1', myvec) 
#[1] "chr2:213403244" "chr7:55240586" "chr7:55241607" 

检查有不同的 'N'

n <- 3 

,并重复同样的步骤

sub(pat, '\\1', myvec) 
#[1] "chr2:213403244:213403244" "chr7:55240586:55240586" 
#[3] "chr7:55241607:55241607" 

或者另一种选择被拆分为:,然后再将paste这n个组件组合在一起。

n <- 2 
vapply(strsplit(myvec, ':'), function(x) 
      paste(x[seq.int(n)], collapse=':'), character(1L)) 
#[1] "chr2:213403244" "chr7:55240586" "chr7:55241607" 
+0

谢谢,你能解释一下在这里做什么。我们如何使用这个nth':'? – MAPK

+0

没有意识到你有我发布的解决方案,所以我删除它。 – hwnd

3

以下是几种选择。在我们删除第k个冒号后面的所有内容。问题中的示例将对应于k = 2。在下面的示例中,我们使用k = 3。

1)read.table将数据读入数据。帧,挑出所需的列和它一起再次粘贴回:

k <- 3 # keep first 3 fields only 
do.call(paste, c(read.table(text = myvec, sep = ":")[1:k], sep = ":")) 

,并提供:

[1] "chr2:213403244:213403244" "chr7:55240586:55240586" 
[3] "chr7:55241607:55241607" 

2)的sprintf /子构建在K以下相等的情况下,适当的正则表达式( 3这将是^((.*?:){2}.*?):.*),并与sub使用它:

k <- 3 
sub(sprintf("^((.*?:){%d}.*?):.*", k-1), "\\1", myvec) 

捐赠:

[1] "chr2:213403244:213403244" "chr7:55240586:55240586" 
[3] "chr7:55241607:55241607" 

注1:对于k = 1这可以进一步简化为sub(":.*", "", myvec)和对于k = n-1个也可以是进一步简化为sub(":[^:]*$", "", myvec)

注2:这里是一个可视化

^((.*?:){2}.*?):.* 

Regular expression visualization

:正规正则表达式 k等于3的

Debuggex Demo

3)反复删除最后一个字段我们可以使用注意事项1,最后的正则表达式中删除最后一个字段n-k倍以上这样的:

n <- 6 # number of fields 
k < - 3 # number of fields to retain 
out <- myvec 
for(i in seq_len(n-k)) out <- sub(":[^:]*$", "", out) 

如果我们希望以设定n自动我们可以有选择地用上述替代上面的硬编码线设置n:

n <- count.fields(textConnection(myvec[1]), sep = ":") 

4)找到第k个冒号的位置使用gregexpr找到冒号的位置,然后从中提取第k个位置,因为我们不需要尾随冒号。使用substr从各个字符串中提取许多字符。

k <- 3 
substr(myvec, 1, sapply(gregexpr(":", myvec), "[", k) - 1) 

,并提供:

[1] "chr2:213403244:213403244" "chr7:55240586:55240586" 
[3] "chr7:55241607:55241607" 

注3:假设有N个字段。该问题要求删除第k个分隔符后面的所有内容,以便解决方案适用于k = 1,2,...,n-1。它不需要为k = n工作,因为没有n个分隔符;然而,如果我们将k定义为要返回的字段数,那么k = n是合理的,事实上,(1)和(3)也适用于这种情况。 (2)和(4)不适用于此扩展,但我们可以通过使用paste0(myvec, ":")而不是myvec来轻松地使它们工作。

注4:我们比较性能:

library(rbenchmark) 
benchmark(
.read.table = do.call(paste, c(read.table(text = myvec, sep = ":")[1:k], sep = ":")), 
.sprintf.sub = sub(sprintf("^((.*?:){%d}.*?):.*", k-1), "\\1", myvec), 
.for = { out <- myvec; for(i in seq_len(n-k)) out <- sub(":[^:]*$", "", out)}, 
.gregexpr = substr(myvec, 1, sapply(gregexpr(":", myvec), "[", k) - 1), 
    order = "elapsed", replications = 1000)[1:4] 

,并提供:

  test replications elapsed relative 
2 .sprintf.sub   1000 0.11 1.000 
4 .gregexpr   1000 0.14 1.273 
3   .for   1000 0.15 1.364 
1 .read.table   1000 2.16 19.636 

使用sprintf和子的解决方案是最快的,虽然它使用一个复杂的正则表达式,而其他人使用简单或没有正则表达式,并可能因简单性而被优选。

ADDED增加了额外的解决方案和附加注释。

相关问题