Векторизация с помощью multidplyr не дает правильного вывода - PullRequest
0 голосов
/ 08 июня 2018

Я попытался распараллелить ape::dist_topo(), функцию для вычисления расстояний между необращенными деревьями.

Обычно функция работает следующим образом (представьте: 4 случайных дерева с 5 листьями в каждом):

library(tidyverse)
# devtools::install_github("hadley/multidplyr")
library(multidplyr)
library(ape)
set.seed(3)

trees <- 
  map(rep(5, 4), rtree) %>% 
  do.call(c.phylo, .) %>% # To transform my list of phylo objects in a multiPhylo object
  unroot.multiPhylo()

dist.topo(trees)
#      tree1 tree2 tree3
# tree2     4            
# tree3     4     2      
# tree4     4     4     2

Я создал функцию для вычисления расстояний 2 на 2 в data.frame (вдля разделения на кластеры по строкам):

dist.topo2 <- function(multiphylo){
  expand.grid(multiphylo, multiphylo) %>% 
    as.tibble() %>% 
    mutate(dist = map2(Var1, Var2, dist.topo)) %>% 
    pull(dist) %>% 
    matrix(., nrow = sqrt(length(.))) %>% 
    as.dist()
}

dist.topo2(trees)
#   1 2 3
# 2 4    
# 3 4 2  
# 4 4 4 2

Как и ожидалось, результат одинаков (независимо от имен).

Затем я добавил функции multidplyr::partition() и multidplyr::collect()в моем конвейере:

dist.topo3 <- function(multiphylo){
  expand.grid(multiphylo, multiphylo) %>% 
    as.tibble() %>% 
    partition() %>%
    mutate(dist = purrr::map2(Var1, Var2, ape::dist.topo)) %>% 
    collect() %>%
    pull(dist) %>% 
    matrix(., nrow = sqrt(length(.))) %>% 
    as.dist()
}

dist.topo3(trees)
#   1 2 3
# 2 4    
# 3 0 4  
# 4 2 4 4
# Warning messages:
# 1: In bind_rows_(x, .id) :
#   Vectorizing 'multiPhylo' elements may not preserve their attributes
# 2: In bind_rows_(x, .id) :
#   Vectorizing 'multiPhylo' elements may not preserve their attributes
# 3: In bind_rows_(x, .id) :
#   Vectorizing 'multiPhylo' elements may not preserve their attributes
# 4: In bind_rows_(x, .id) :
#   Vectorizing 'multiPhylo' elements may not preserve their attributes
# 5: In bind_rows_(x, .id) :
#   Vectorizing 'multiPhylo' elements may not preserve their attributes
# 6: In bind_rows_(x, .id) :
#   Vectorizing 'multiPhylo' elements may not preserve their attributes

Как видите, расстояния разные, тогда как операции не изменились.

Как я могу это исправить?Может быть, это невозможно ( См. Здесь )

Спасибо

Примечание: я знаю, что это решение может быть неоптимальным (особенно потому, что оно вычисляет каждое расстояние два раза) но это не главное.

Ответы [ 2 ]

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

Проблема в том, что partition будет случайным образом отбрасывать data.frame, а collect будет случайным образом отбрасывать data.frame.Если вы добавляете номер строки в виде столбца и упорядочиваете после сбора, это устраняет проблему

dist.topo3 <- function(multiphylo){
  expand.grid(multiphylo, multiphylo) %>% 
    as.tibble() %>% 
    mutate(rn = row_number()) %>%
    partition(rn) %>%
    mutate(dist = purrr::map2(Var1, Var2, ape::dist.topo)) %>% 
    collect() %>%
    arrange(rn) %>%
    pull(dist) %>% 
    matrix(., nrow = sqrt(length(.))) %>% 
    as.dist()
}
dist.topo3(trees)
#   1 2 3
# 2 4    
# 3 4 2  
# 4 4 4 2
0 голосов
/ 08 июня 2018

Я бы лучше использовал пакет {furrr}, чем {multidplyr}:

library(furrr)
plan(multiprocess)

dist.topo4 <- function(multiphylo) {

  dists <- expand.grid(multiphylo, multiphylo) %>% 
    setNames(c("x", "y")) %>%
    future_pmap_dbl(ape::dist.topo)

  n <- length(multiphylo)
  dim(dists) <- c(n, n)

  as.dist(dists)
}

Результат

> dist.topo4(trees)
  1 2 3
2 4    
3 4 2  
4 4 4 2
...