2015-10-11 31 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增加了額外的解決方案和附加註釋。

相關問題