Как улучшить производительность пользовательской функции с помощью ручной векторизации в R - PullRequest
0 голосов
/ 25 апреля 2019

У меня есть два фрейма данных: df1, предоставляющий координаты заданных символов, и df2, предоставляющий начальную и конечную координаты. Мне нужно получить последовательность символов между каждой начальной и конечной координатами в df2.

Например:

set.seed(1)
df1 <- data.frame(POS = 1:10000000,
              REF = sample(c("A", "T", "G", "C"), 10000000, replace = T))

df2 <- data.frame(start = sample(1:5000000, 10, replace = T),
                 end = sample(5000001:10000000, 10, replace = T))

Я пытался использовать цикл for:

system.time( {                
df2$seq <- NA
for(i in 1:nrow(coords)){
  df2$seq[i] <- paste(ref$REF [ c( which(ref$POS == coords$start[i]) : which(ref$POS == coords$end[i]) ) ], collapse = "")
}
})

И с использованием ручной векторизации:

mongoose <- function(from, to){
  string <- paste(
    ref$REF [ c( which(ref$POS == from) : which(ref$POS == to) ) ],
    collapse = "")
  return(string)
}

mongoose_vec <- Vectorize(mongoose, vectorize.args = c("from", "to"))

system.time({
  sequences <- mongoose_vec(from = df2$start, to = df2$end)
  })

Однако оба эти метода работают с одинаковыми скоростями и недостаточно быстры, поскольку набор данных, к которому я их применяю, очень велик. У кого-нибудь есть предложения по улучшению производительности?

1 Ответ

0 голосов
/ 25 апреля 2019

Векторизация не значительно ускорит вашу задачу, поскольку она просто уменьшает накладные расходы, но большая часть вычислений выполняется внутри самого цикла.

Один из подходов, который вы можете использовать, - это сохранить ref в виде длинной строки и использовать функцию substr.

ref2 <- paste0(ref$REF, collapse="")
system.time({
sequences2 <- sapply(1:nrow(coords), function(i) {
  substr(ref2, coords$start[i], coords$end[i])
})
})

user  system elapsed 
  0.135   0.010   0.145 

Ваш оригинальный код:

system.time({
  sequences <- mongoose_vec(from = coords$start, to = coords$end)
})

   user  system elapsed 
  7.914   0.534   8.461 

Результаты идентичны:

identical(sequences, sequences2) 
TRUE

PS: я предполагаю, что df1 - это ref, а df2 - это coords.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...