(1) gsubfnこのgsubfn
ステートメントは、^... の部分をその長さをスペースで囲んだものに置き換え、strapply
その文字列から数字を抜き出して数値に変換します。strapply
文字出力で十分な場合は省略します。
> library(gsubfn)
> xx <- gsubfn("\\^[ACGT]*", ~ sprintf(" %s ", nchar(x) - 1), x)
> strapply(xx, "\\d+", as.numeric)
[[1]]
[1] 16 2 40
(2) 長さのセットをループ
これは、各 ACGT シーケンスの文字数が mn から mx の間であると仮定し、ループ内で処理を進める gsub を使用して、i long の ACGT シーケンスを i に置き換えるだけです。可能な長さがわずかしかない場合は、数回の反復しかないため高速ですが、文字列がさまざまな長さを持つ可能性がある場合は、ループの反復がさらに必要になるため遅くなります。以下では、ACGT シーケンスの長さは 2、4、または 6 であると想定していますが、これらは調整する必要がある場合があります。このソリューションの考えられる欠点は、一連の可能なシーケンス長を想定する必要があることです。
x <- "4^CG5^CAGT656"
mn <- 2
mx <- 6
y <- x
for(i in seq(mn, mx, 2)) {
pat <- sprintf("\\^[ACGT]{%d}(\\d)", i)
replacement <- sprintf(" %d \\1", i)
y <- gsub(pat, replacement, y)
}
(3) ACGT シーケンスのループ
この 1 つは、ACGT シーケンスをループし、1 つをその長さに置き換えて、何も残らなくなるまで繰り返します。ACGT シーケンスの数が少ない場合は反復回数が少ないため高速になりますが、ACGT シーケンスの数が多い場合は反復回数が多くなるため遅くなります。
x <- "4^CG5^CAGT656"
y <- x
while(regexpr("^", y, fixed = TRUE) > 0) {
y <- sprintf("%s %d %s", sub("\\^.*", "", y),
nchar(sub("^[0-9 ]+\\^([ACGT]+).*", "\\1", y)),
sub("^[0-9 ]+\\^[ACGT]+", "", y))
}
基準
これがベンチマークです。上記のいくつかのソリューションでは、文字列を数値に変換しましたが (もちろん、これには余分な時間がかかります)、ベンチマークを比較できるようにするために、数値変換なしで文字列を作成する速度を比較しました。
x <- "4^CGT5^CCA656"
library(rbenchmark)
benchmark(order = "relative", replications = 10000,
columns = c("test", "replications", "relative", "elapsed"),
regmatch = {
pat <- "(\\^[ACGT]+)"
x2 <- x
m <- gregexpr(pat, x2)
regmatches(x2, m) <- sapply(regmatches(x2, m), modFun)
x2
},
gsubfn = gsubfn("\\^[ACGT]*", ~ sprintf(" %s ", length(x) - 1), x),
loop.on.len = {
mn <- 2
mx <- 6
y <- x
for(i in seq(mn, mx, 2)) {
pat <- sprintf("\\^[ACGT]{%d}(\\d)", i)
replacement <- sprintf(" %d \\1", i)
y <- gsub(pat, replacement, y)
}
},
loop.on.seq = {
y <- x
while(regexpr("^", y, fixed = TRUE) > 0) {
y <- sprintf("%s %d %s", sub("\\^.*", "", y),
nchar(sub("^[0-9 ]+\\^([ACGT]+).*", "\\1", y)),
sub("^[0-9 ]+\\^[ACGT]+", "", y))
}
}
)
結果を以下に示します。2 つのループ ソリューションは、示された入力で最も高速でしたが、必要な反復回数によってパフォーマンスが異なるため、実際のデータによって違いが生じる可能性があります。loop.on.len ソリューションには、ACGT の長さが想定されたセットの中になければならないという欠点があります。Josh の regmatch ソリューションは、ループがなく、高速です。gsubfn ソリューションには、コードが 1 行しかなく、特に直接的であるという利点があります。
test replications relative elapsed
4 loop.on.seq 10000 1.000 1.93
3 loop.on.len 10000 1.140 2.20
1 regmatch 10000 1.803 3.48
2 gsubfn 10000 7.145 13.79
更新 2 つのループ ソリューションを追加し、複数の ACGT シーケンスを処理しない以前の投稿の一部であったソリューションを削除しました (質問を明確にするコメントに基づく)。また、複数の ACGT シーケンスを処理するソリューションのみを含むベンチマークをやり直しました。
更新複数の ^... シーケンスで機能しない 1 つのソリューションを削除しました。以前にベンチマークから削除されていましたが、コードは削除されていませんでした。(1)の説明を改善。