我有这个矢量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
我有这个矢量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
我们可以使用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"
以下是几种选择。在我们删除第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}.*?):.*
:正规正则表达式
k
等于3的
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增加了额外的解决方案和附加注释。
谢谢,你能解释一下在这里做什么。我们如何使用这个nth':'? – MAPK
没有意识到你有我发布的解决方案,所以我删除它。 – hwnd