Быстрое объединение и перенос многих файлов наборов данных фиксированного формата

Что у меня есть: ~100 текстовых файлов, каждый имеет 9 столбцов и>100 000 строк. Что я хочу: комбинированный файл, содержащий только 2 столбца, но все строки. тогда это должно быть транспонировано для вывода>100 000 столбцов и 2 строк.

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

Проблема: Это хорошо работает на моих маленьких тестовых файлах, но когда я пытаюсь сделать это на больших файлах, я сталкиваюсь с проблемой выделения памяти. Моих 8 ГБ ОЗУ просто недостаточно, и я предполагаю, что часть этого заключается в том, как я написал свой код.

Мой вопрос: есть ли способ перебрать файлы, а затем объединить все сразу в конце, чтобы сэкономить время обработки?

Кроме того, если это неправильное место для подобных вещей, что может быть лучше для получения информации о коде WIP?

##Script to pull in genotype txt files, transpose them, delete commented rows & 
## & header rows, and then put files together.

library(plyr)

## Define function
Process_Combine_Genotype_Files <- function(
        inputdirectory = "Rdocs/test", outputdirectory = "Rdocs/test", 
        template = "Rdocs/test/template.txt",
        filetype = ".txt", vars = ""
        ){

## List the files in the directory & put together their path
        filenames <- list.files(path = inputdirectory, pattern = "*.txt")
        path <- paste(inputdirectory,filenames, sep="/")


        combined_data <- read.table(template,header=TRUE, sep="\t")

## for-loop: for every file in directory, do the following
        for (file in path){

## Read genotype txt file as a data.frame
                currentfilename  <- deparse(substitute(file))
                currentfilename  <- strsplit(file, "/")
                currentfilename <- lapply(currentfilename,tail,1)

                data  <- read.table(file, header=TRUE, sep="\t", fill=TRUE)

                #subset just the first two columns (Probe ID & Call Codes)
                #will need to modify this for Genotype calls....
                data.calls  <- data[,1:2]

                #Change column names & row names
                colnames(data.calls)  <- c("Probe.ID", currentfilename)
                row.names(data.calls) <- data[,1]


## Join file to previous data.frame
                combined_data <- join(combined_data,data.calls,type="full")


## End for loop
        }
## Merge all files
        combined_transcribed_data  <- t(combined_data)
print(combined_transcribed_data[-1,-1])
        outputfile  <- paste(outputdirectory,"Genotypes_combined.txt", sep="/")        
        write.table(combined_transcribed_data[-1,-1],outputfile, sep="\t")

## End function
}

Заранее спасибо.

2 ответа

Решение

Пытаться:

filenames <- list.files(path = inputdirectory, pattern = "*.txt")
require(data.table)
data_list <- lapply(filenames,fread, select = c(columns you want to keep))

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

data <- rbindlist(data_list)

перенос данных:

t(data)

(Спасибо @Jakob H за select в дураках)

Если важна скорость / рабочая память, я бы порекомендовал использовать Unix для слияния. В общем, Unix быстрее, чем R. Кроме того, Unix не требует загрузки всей информации в ОЗУ, а считывает информацию порциями. Следовательно, Unix никогда не ограничивается памятью. Если вы не знаете Unix, но планируете часто манипулировать большими файлами в будущем, изучите Unix. Это просто учиться и очень мощный. Я сделаю пример с CSV-файлами.

Генерация CSV-файлов в R

for (i in 1:10){
  write.csv(matrix(rpois(1e5*10,1),1e5,10), paste0('test',i,'.csv'))
}

В оболочке (то есть на Mac)/ Терминале (то есть на Linux Box)/Cygwin (то есть в Windows)

cut -f 2,3 -d , test1.csv > final.csv #obtain column 2 and 3 form test1.csv
cut -f 2,3 -d , test[2,9].csv test10.csv | sed 1d >> final.csv #removing header in test2.csv onward 

Обратите внимание, что если вы установили Rtools, вы можете запустить все эти команды Unix из R с помощью команды system функция.

Для транспонирования прочитайте final.csv в R и транспонируйте.

ОБНОВИТЬ:

Я рассчитал приведенный выше код. Это заняло 0,4 секунды. Следовательно, чтобы сделать это для 100 файлов, а не только для 10 файлов, это, вероятно, займет 4 секунды. Я не рассчитывал время написания кода R, однако, возможно, что программы Unix и R имеют одинаковую производительность, когда имеется всего 10 файлов, однако при наличии более 100 файлов ваш компьютер, вероятно, станет связанным с памятью, а R, скорее всего, вылетит.,

Другие вопросы по тегам