R - Оптимизировать преобразование структуры данных - PullRequest
0 голосов
/ 02 мая 2019

У меня есть тиббл в аккуратном формате с тремя атрибутами - серией, одним из его возможных следующих элементов и вероятностью следующего элемента.

library(dplyr)
bases <- sapply(1:20, function(x){paste(sample(letters[1:3], 3, replace = T), collapse = " ")})
nplus1 <- sample(letters, 20, replace = T)
probs <- runif(20)
t <- as_tibble(data.frame(bases, nplus1, probs))

head(t)
# A tibble: 6 x 3
  bases nplus1  probs
  <fct> <fct>   <dbl>
1 b a c r      0.409 
2 c b b p      0.176 
3 a b c s      0.468 
4 a b a n      0.348 
5 b a b c      0.733 
6 b a b e      0.0525

В конце концов, я бы хотел использовать list2env(), чтобы выполнить поиск по хэшу по базе. Для этого я разделил таблицу на список таблиц, сгруппированных по базе, используя split(). Тиблы имеют порядка миллионов строк, и split() достаточно быстр.

t_split <- split(t, t$bases)
t_split[1:3]
$`a a c`
# A tibble: 1 x 3
  bases nplus1 probs
  <fct> <fct>  <dbl>
1 a a c i      0.661

$`a b a`
# A tibble: 1 x 3
  bases nplus1 probs
  <fct> <fct>  <dbl>
1 a b a n      0.348

$`a b c`
# A tibble: 2 x 3
  bases nplus1  probs
  <fct> <fct>   <dbl>
1 a b c s      0.468 
2 a b c h      0.0324

Оттуда к списку элементов применяется цикл for для преобразования таблиц с интенсивным использованием памяти в списки. Насколько я понимаю, цикл for работает быстрее при таком преобразовании на месте, чем lapply.

# helper function transforms tibble to vector
flatten <- function(table){
        l <- list(np1 = table$nplus1, probs=table$probs)
        return(l)
}

# for loop
loop <- function(table.list){
        list.names <- names(table.list)
        for( n in list.names ){
                table.list[[n]] <- flatten(table.list[[n]])
        }
        table.list <- setNames(table.list, list.names)
        return(table.list)
}

loop(t_split)

Несмотря на то, что шаг разделения по группам является быстрым, четыре цикла, которые сглаживают отдельные элементы, занимают целую вечность, около 12 часов для нерасщепленной таблицы с примерно 1,5 миллионами строк.

Что-то выделяется здесь как особенно неэффективное? Есть ли лучший и более быстрый способ переформатировать эти данные?

...