Поиск комбинаций векторов из пар элементов списка - PullRequest
0 голосов
/ 25 июня 2018

У меня есть именованный список, представляющий коллекцию биологических путей, где имена - это имена путей, а векторы в списке - это белки, которые принадлежат этому пути. Небольшой пример:

ann <- structure(list(`GO:0000010` = c("Q33DR2", "Q9CZQ1", "D6RHT8", 
"F6ZCX7", "B8JJX0", "Q33DR3", "F6T4Z4", "E0CYM9"), `GO:0000016` = c("Q5XLR9", 
"Q3TZ78", "F8VPT3"), `GO:0000026` = c("Q8BTP0", "Q3TZM9", "A0A077K846", 
"F6R220", "A0A077K9W9"), `GO:0000032` = c("Q924M7", "Q3V100", 
"F6Q3K8", "Q921Z9"), `GO:0000033` = c("Q9DBE8", "F6RBY3", "Q8BMZ4", 
"Q8K2A8", "F6XUH0", "D6RCW8", "Q6P8H8", "Q3URN2")), .Names = c("GO:0000010", 
"GO:0000016", "GO:0000026", "GO:0000032", "GO:0000033"))

Меня интересуют пары путей:

pairs <- t(combn(names(ann), 2))

Для каждой пары путей я хочу получить все возможные комбинации белков, где белок № 1 находится в пути № 1, а белок № 2 находится в пути № 2. Желаемый результат - список двухколоночных матриц, где столбец № 1 содержит белки в пути № 1, а столбец № 2 содержит белки в пути № 2. Пока у меня есть это:

protein_pairs <- purrr::map2(pairs[, 1], pairs[, 2], ~ as.matrix(expand.grid(ann[[.x]], ann[[.y]])))

Однако, поскольку общее количество пар, которые меня интересуют, достаточно велико (обычно> 1000), отображение expand.grid по всем возможным парам занимает очень много времени - порядка часов.

Существует ли более быстрый способ получить все возможные комбинации белков в каждой паре биологических путей из этого списка?

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

Если вы ищете скорость, вы можете легко разыграть версию Rcpp:

// [[Rcpp::export]]
CharacterMatrix fast2Expand(CharacterVector x, CharacterVector y) {

    unsigned long int lenX = x.size(), lenY = y.size();
    CharacterMatrix result = no_init_matrix(lenX * lenY, 2);

    for (std::size_t i = 0, count = 0; i < lenY; ++i) {
        for (std::size_t j = 0; j < lenX; ++j, ++count){
            result(count, 0) = x[j];
            result(count, 1) = y[i];
        }
    }

    return result;
}

Это примерно на 10x быстрее, чем оригинал и 20%, чем rep.int версия(для этого примера):

microbenchmark(OP = purrr::map2(pairs[, 1], pairs[, 2], ~ as.matrix(expand.grid(ann[[.x]], ann[[.y]]))),
               Rcpp = purrr::map2(pairs[, 1], pairs[, 2], ~ fast2Expand(ann[[.x]], ann[[.y]])),
               repInt = purrr::map2(pairs[, 1], pairs[, 2], ~ as.matrix(expand.grid.jc(ann[[.x]], ann[[.y]]))))
Unit: microseconds
  expr      min        lq      mean    median        uq      max neval
    OP 1104.700 1136.4370 1536.4048 1188.9990 1481.4940 6730.960   100
  Rcpp  105.505  126.9975  149.9009  138.1195  150.2015  663.146   100
repInt  133.044  151.0175  223.9815  165.5435  203.5335 1269.194   100

Вот надуманный пример, основанный на примере ОП, предназначенном исключительно для сравнения эффективности:

annBig <- lapply(1:5, function(x) rep(ann[[x]], 100))
names(annBig) <- names(ann)

microbenchmark(OP = purrr::map2(pairs[, 1], pairs[, 2], ~ as.matrix(expand.grid(annBig[[.x]], annBig[[.y]]))),
               Rcpp = purrr::map2(pairs[, 1], pairs[, 2], ~ fast2Expand(annBig[[.x]], annBig[[.y]])),
               repInt = purrr::map2(pairs[, 1], pairs[, 2], ~ as.matrix(expand.grid.jc(annBig[[.x]], annBig[[.y]]))), times = 20)
Unit: milliseconds
  expr       min        lq      mean    median       uq      max neval
    OP 522.56536 533.39393 562.60750 555.45345 588.4514 640.8584    20
  Rcpp  48.12683  56.17155  92.30095  92.23838 125.8065 142.2949    20
repInt  80.28625 107.32329 140.32793 152.13732 160.9656 193.1310    20
0 голосов
/ 25 июня 2018

Я считаю rep.int() работает намного быстрее, как указано в этом другом вопросе:

Попробуйте следующее:

expand.grid.jc <- function(seq1,seq2) {
  cbind(Var1 = rep.int(seq1, length(seq2)), 
        Var2 = rep.int(seq2, rep.int(length(seq1),length(seq2))))
}
protein_pairs <- purrr::map2(pairs[, 1], pairs[, 2], ~ as.matrix(expand.grid.jc(ann[[.x]], ann[[.y]])))

Приветствия !,

...