2012-05-01 2 views
3

Я хочу знать, как векторизовать и запоминать пользовательскую функцию в R. Кажется мой образ мышления не совпадает с образом работы R. Итак, я с удовольствием приветствую любые ссылки на хорошие материалы для чтения. Например, R инферна хороший ресурс, но это не помогло выяснить запоминание в R.Запомните и векторизовать пользовательскую функцию

В целом, вы можете предоставить соответствующий пример использования для memoise или R.cache пакетов?

Мне не удалось найти других обсуждений по этому вопросу. Поиск для «memoise» или «memoize» на r-bloggers.com возвращает нулевые результаты. Поиск по этим ключевым словам по адресу http://r-project.markmail.org/ не возвращает полезный обсуждений. Я отправил по электронной почте список рассылки и не получил полный ответ .

Меня интересуют не только воспоминания о функции GC, и я знаю о Доступен биокондуктор и различные пакеты .

Вот мои данные:

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 

Я хочу memoize его. Затем я хочу его векторизовать.

Видимо, я должен иметь неправильное мышление для использования memoise или R.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 

Обратите внимание, что memoized функции на несколько порядков медленнее.

Я пробовал пакет 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 сообщений:

+0

Любая конкретная причина, вы не обращая внимания на то, что 'nchar' и' gregexpr' уже векторизованы? –

ответ

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 
} 
+0

В моей системе (x86_64 linux-gnu R 2.15.0) ваша функция ~ в 3 раза медленнее. Я тестирую скорость следующим образом: 'system.time (sapply (rep (seqs, 1000), GC))' получает 0,418 истекших секунд. 'system.time (sapply (rep (seqs, 1000), GC2))' получает 1.401 истекших секунд. –

+0

@KamilSlowikowski Это потому, что вы используете эту функцию неправильно. Джошуа его векторизовал, поэтому вы должны сравнить его с «GC2 (rep (seqs, 1000))», и в этом случае он действительно ~ 4 раза быстрее. – joran

+0

@KamilSlowikowski Хотя я думаю, что он не хотел устанавливать 'fixed = TRUE'. – joran

2

Хотя это не даст вам запоминание через вызовы, вы можете использовать факторы, чтобы сделать индивидуальные звонки намного быстрее, если есть справедливый бит повторения. Например, с помощью GC2 Джошуа (хотя я должен был удалить фиксированный = 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 
+0

Это замечательно. Спасибо! Воспоминание спасет меня относительно небольшое количество времени отсюда. –

Смежные вопросы