2015-11-17 3 views
2

Я пытаюсь прочитать и объединить несколько текстовых файлов в R. Проблема заключается в том, что мне были предоставлены некоторые данные, где разделители полей между файлами различны (например, вкладка для одного и запятые для другого). Как я могу объединить их эффективно? Пример компоновки:объединение текстовых файлов в R с разными разделителями

Data1 (закладка):

v1 v2 v3 v4 v5 
1 2 3 4 urban 
4 5 3 2 city 

Data2 (запятая):

v1,v2,v3,v4,v5 
5,6,7,8,rural 
6,4,3,1,city 

Этот пример, очевидно, не реальный, реальный код имеет почти полмиллиона очков! И поэтому невозможно изменить исходные файлы. Код, который я использовал до сих пор было:

filelist <- list.files(path = "~/Documents/", pattern='.dat', full.names=T) 
data1 <- ldply(filelist, function(x) read.csv(x, sep="\t")) 
data2 <- ldply(filelist, function(x) read.csv(x, sep=",")) 

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

+0

вы пробовали 'fread' из "data.table" в качестве альтернативы' чтения .csv'? Он может, как правило, автоматически определять разделители, сканируя файл. – A5C1D2H2I1M1N2O1R2T1

ответ

2

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

Вот пример:

## Create some example files 
cat('v1\tv2\tv3\tv4\tv5\n1\t2\t3\t4\turban\n4\t5\t3\t2\tcity\n', file = "file1.dat") 
cat('v1,v2,v3,v4,v5\n5,6,7,8,rural\n6,4,3,1,city\n', file = "file2.dat") 

## Get a character vector of the file names 
files <- list.files(pattern = "*.dat") ## Use what you're already doing 

library(data.table) 
lapply(files, fread) 
# [[1]] 
# v1 v2 v3 v4 v5 
# 1: 1 2 3 4 urban 
# 2: 4 5 3 2 city 
# 
# [[2]] 
# v1 v2 v3 v4 v5 
# 1: 5 6 7 8 rural 
# 2: 6 4 3 1 city 

## Fancy work: Bind it all to one data.table... 
## with a column indicating where the file came from.... 
rbindlist(setNames(lapply(files, fread), files), idcol = TRUE) 
#   .id v1 v2 v3 v4 v5 
# 1: file1.dat 1 2 3 4 urban 
# 2: file1.dat 4 5 3 2 city 
# 3: file2.dat 5 6 7 8 rural 
# 4: file2.dat 6 4 3 1 city 
+0

Спасибо за совет - пакет действительно полезен! – GeeMiss

1

Вы также можете добавить if пункт в вашей функции:

data = ldply(filelist,function(x) if(grepl(",",readLines(x,n=1))){read.csv(x,sep=",")} else{read.csv(x,sep="\t")}) 
+1

Это хорошая идея (+1), но я бы опасался использовать 'grep'. возможно, 'count.fileds' - лучшая альтернатива, например:' lapply (files, function (x) if (count.fields (textConnection (readLines (x, 1)), sep = ",") [1] == 5) read.csv (x) else read.delim (x)) '. – A5C1D2H2I1M1N2O1R2T1

+0

Спасибо ~ но что вы беспокоитесь, вы имеете в виду, что grep не может точно определить разделитель? И мне нравится ваш read.delim(), кстати:) – Gentlezerg

+0

Я предполагаю, что вряд ли заголовок будет иметь вкладки или запятые в качестве данных, поэтому моя осторожность, скорее всего, необоснованна ... Казалось бы, имеет смысл использовать что 'read.table' использует под капотом, тем более что это дает нам что-то удобное для проверки, поскольку мы знаем структуру исходных данных .... – A5C1D2H2I1M1N2O1R2T1

Смежные вопросы