4

Rでカスタム関数をベクトル化してメモ化する方法を知りたい.私の考え方はRの操作方法と一致していないようです. ですから、良い読み物へのリンクを喜んで歓迎します。たとえば、R inferno は優れたリソースですが、R でのメモ化を理解するのには役立ちませんでした。

memoise より一般的には、またはR.cacheパッケージの関連する使用例を提供できますか?

この件に関する他の議論を見つけることができませんでした。r-bloggers.com で「memoise」または「memoize」を検索しても、結果はゼロです。http://r-project.markmail.org/でこれらのキーワードを検索しても、役立つ議論は返されません。メーリング リストに電子メールを送信しましたが、完全な回答がありませんでした。

私は GC 関数のメモ化だけに興味があるわけではなく、Bioconductor とそこで利用できるさまざまなパッケージについても知っています。

ここに私のデータがあります:

seqs <- c("","G","C","CCC","T","","TTCCT","","C","CTC")

一部のシーケンスが欠落しているため、空白""です。

GC コンテンツを計算する関数があります。

> GC <- function(s) {
    if (!is.character(s)) return(NA)
    n <- nchar(s)
    if (n == 0) return(NA)
    m <- gregexpr('[GCSgcs]', s)[[1]]
    if (m[1] < 1) return(0)
    return(100.0 * length(m) / n)
}

できます:

> GC('')
[1] NA
> GC('G')
[1] 100
> GC('GAG')
[1] 66.66667
> sapply(seqs, GC)
                  G         C       CCC         T               TTCCT           
       NA 100.00000 100.00000 100.00000   0.00000        NA  40.00000        NA 
        C       CTC 
100.00000  66.66667

メモしたい。次に、それをベクトル化したい。

どうやら、memoiseまたは R.cacheR パッケージを使用するための考え方が間違っているに違いありません。

> system.time(dummy <- sapply(rep(seqs,100), GC))
   user  system elapsed
  0.044   0.000   0.054
>
> library(memoise)
> GCm1 <- memoise(GC)
> system.time(dummy <- sapply(rep(seqs,100), GCm1))
   user  system elapsed
  0.164   0.000   0.173
>
> library(R.cache)
> GCm2 <- addMemoization(GC)
> system.time(dummy <- sapply(rep(seqs,100), GCm2))
   user  system elapsed
 10.601   0.252  10.926

メモ化された関数は数桁遅いことに注意してください。

パッケージを試してみましたhashが、裏で何かが起こっているようで、出力がわかりません。シーケンスの値はではなくCでなければなりません。100NULL

has.key(s, cache)の代わりに使用するexists(s, cache)と、同じ出力が得られることに注意してください。また、cache[s] <<- result代わりに 使用するcache[[s]] <<- resultと、同じ出力が得られます。

> cache <- hash()
> GCc <- function(s) {
    if (!is.character(s) || nchar(s) == 0) {
        return(NA)
    }
    if(exists(s, cache)) {
        return(cache[[s]])
    }
    result <- GC(s)
    cache[[s]] <<- result
    return(result)
}
> sapply(seqs,GCc)
[[1]]
[1] NA

$G
[1] 100

$C
NULL

$CCC
[1] 100

$T
NULL

[[6]]
[1] NA

$TTCCT
[1] 40

[[8]]
[1] NA

$C
NULL

$CTC
[1] 66.66667

少なくとも、ベクトル化する方法を見つけました。

> GCv <- Vectorize(GC)
> GCv(seqs)
                  G         C       CCC         T               TTCCT           
       NA 100.00000 100.00000 100.00000   0.00000        NA  40.00000        NA 
        C       CTC 
100.00000  66.66667 

関連するスタックオーバーフローの投稿:

4

2 に答える 2

2

これは複数の呼び出しにまたがってメモ化することはできませんが、繰り返しがかなりある場合は、係数を使用して個々の呼び出しを大幅に高速化できます。たとえば、Joshua の GC2 を使用する場合 (ただし、fixed=T を削除して動作させる必要がありました):

GC2 <- function(s) {
  if(!is.character(s)) stop("'s' must be character")
  n <- nchar(s)
  m <- gregexpr('[GCSgcs]', s)
  len <- sapply(m, length)
  neg <- sapply(m, "[[", 1)
  len <- len*(neg > 0)
  100.0 * len/n
}

次のようなラッパーを簡単に定義できます。

GC3 <- function(s) {
  x <- factor(s)
  GC2(levels(x))[x]
}

system.time(GC2(rep(seqs, 50000)))
# user  system elapsed 
# 8.97    0.00    8.99 
system.time(GC3(rep(seqs, 50000)))
# user  system elapsed 
# 0.06    0.00    0.06 
于 2012-05-01T22:55:51.563 に答える
1

これはあなたの質問に明確に答えるものではありませんが、この関数はあなたのものよりも最大 4 倍高速です。

GC2 <- function(s) {
  if(!is.character(s)) stop("'s' must be character")
  n <- nchar(s)
  m <- gregexpr('[GCSgcs]', s)
  len <- sapply(m, length)
  neg <- sapply(m, "[[", 1)
  len <- len*(neg > 0)
  len/n
}
于 2012-05-01T22:12:21.503 に答える