记住并矢量化自定义功能

时间:2012-05-01 21:18:44

标签: r vectorization memoization

我想知道如何在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

我想记住它。然后,我想对它进行矢量化。

显然,我必须有错误的心态来使用memoiseR.cache R包:

> 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应该有一个 价值100,而不是NULL

请注意,使用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 

相关的stackoverflow帖子:

2 个答案:

答案 0 :(得分: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 

答案 1 :(得分: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
}