В вычислительном отношении самый быстрый способ объединения данных из нескольких файлов в один data.frame в R? - PullRequest
0 голосов
/ 26 марта 2020

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

test = read.delim("814630", head = F)
head(test)
      V1   V2
1 814630 0.00
2 839260 1.95
3 841877 2.59
4 825359 4.95
5 834026 5.16
6 825107 6.21

Затем я делаю это для чтения файлов (в Например, я только что прочитал 5 файлов):

> temp = list.files()
> length(temp)
[1] 20819
> start_time <- Sys.time()
> data = lapply(temp[1:5], read.delim, head=F)
> end_time <- Sys.time()
> end_time - start_time
Time difference of 0.1406569 secs

Если я использую пакет mclapply из parallel, я получаю аналогичное время (когда я делаю это для файлов 20000, это занимает 15-20 минут, любой совет о том, как улучшить это время, тоже поможет):

> library(parallel)
> numCores <- detectCores()
> cl <- makeCluster(numCores)
> data = mclapply(temp[1:5], read.delim, head=F)
Time difference of 0.1495719 secs

Затем я использую left_join из dplyr пакета, чтобы объединить их в один data.frame. Эта вторая часть занимает короткое время с данными из нескольких файлов, но когда я пытаюсь объединить все данные, это занимает гораздо больше времени, чем даже чтение файлов (это может занять несколько часов).

> test = data %>% reduce(left_join,by="V1")
Time difference of 0.05186105 secs

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

Кроме того, вот как будет выглядеть мой последний data.frame после некоторое форматирование. Обратите внимание, что данные представляют собой симметрию c матрицу . Так что, возможно, есть способ чтения только половины данных, который может ускорить процесс.

> row.names(test) = test[,1]
> test[,1] = NULL
> colnames(test) = temp[1:5]
> test = test[order(as.numeric(row.names(test))), order(as.numeric(names(test)))]
> 
> head(test)
         814630   814636   814637  814638   814639
814630     0.00   318.41 13293.00 2012.21   391.97
814636   318.41     0.00  1345.84 1377.79  1889.77
814637 13293.00  1345.84     0.00 6477.10 10638.69
814638  2012.21  1377.79  6477.10    0.00  3905.41
814639   391.97  1889.77 10638.69 3905.41     0.00

1 Ответ

1 голос
/ 26 марта 2020

Простой подход, который предполагает, что все V1 существуют в каждой таблице:

library(dplyr)
V1 <- read.delim(temp[1], head=F) %>% arrange(V1) %>% dplyr::select(-V2)
data = lapply(temp[1:5], function(x) {
    read.delim(x, head=F) %>% arrange(V1) %>% dplyr::select(-V1)
})
test <- cbind(V1, do.call(cbind, data))

Это будет намного быстрее, чем неоднократно left_join, поскольку объединение происходит медленнее, чем больше столбцов / строк, которые у вас есть.

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