чтение в .txt файлах из каталога с помощью R - PullRequest
0 голосов
/ 01 октября 2019

Я пытаюсь прочитать текстовые файлы из каталога, а затем объединить данные из этих файлов в один фрейм данных. Файлы 3 строки по 8125 столбцов. Есть небольшая проблема, которая, я думаю, ставит этот вопрос отдельно от аналогичных вопросов о StackOverflow в том, что файлы (которые создаются программой, которую я использую) не имеют значения в позиции [1,1], и мне интересно, если это бросаетвещи выключены

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

example_data_subset picture

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

Это текущий код, который я использую:

list.filenames<-list.files("run2/", full.names = TRUE)

# create an empty list that will serve as a container to receive the incoming files
list.data<-list()

# create a loop to read in your data

for(i in 1:length(list.filenames)){
  file <- read.table(list.filenames[i], sep="", fill = TRUE) 
  out.file <- rbind(out.file, file)
}

Если я запускаю это, я получаю следующую ошибку:

Error in rbind(deparse.level, ...) : 
  numbers of columns of arguments do not match

Я также пытался

do.call(rbind, lapply(list.filenames, function(x) read.delim(file=x)))

И это тоже не работает, приводя к ошибке:

Error in rbind(deparse.level, ...) : 
  numbers of columns of arguments do not match
In addition: Warning messages:
1: In scan(file = file, what = what, sep = sep, quote = quote, dec = dec,  :
  EOF within quoted string
2: In scan(file = file, what = what, sep = sep, quote = quote, dec = dec,  :
  embedded nul(s) found in input

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

Другой вопрос, который у меня возникает, состоит в том, можно ли считывать по 1 строке за раз из каждого файла и создавать 3 разных файла для 3 разных строк. Но я даже не уверен, с чего начать.

Надеюсь, этот вопрос имеет некоторое подобие смысла.

Спасибо миллион! коллега

1 Ответ

0 голосов
/ 08 октября 2019

Есть два требования, чтобы решить с этим вопросом. Во-первых, нам нужно прочитать набор файлов с одинаковыми столбцами, где файлы хранятся в подкаталоге с расширением .txt. Столбцы в файле данных разделяются символом-разделителем, значение которого не указано в OP.

Во-вторых, в каждом файле отсутствует заголовок столбца, который выглядит как столбец с именем location или type.

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

Мы будем использовать функцию readr::read_csv() для решения этой проблемы, потому что readr::read_csv() позволяет нам указать строки, которые будут считаны из файла данных.

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

Мы реплицировали данные в записи и сохранили две копии их в файлах данных в подкаталоге \data текущего рабочего каталога R. Мы использовали , в качестве разделителя, чтобы сделать его видимым в данных примера.

Данные выглядят следующим образом:

OTU9,OTU6,OTU1972,OTU39,OTU1456,OTU16,OTU58,OTU5
Soil,0,0,0,0,0,0,0,0
Stream,0,0,0,0,0,0,0,0
Unknown,100,0,20,80,0,70,0,70

Обратите внимание, что если разделитель поля данных в фактических данных является символом, отличным от ,, можно указать правильный символ разделителя в read_csv() с аргументом delim=.

Шаг 1: получить имена файлов из подкаталога

Я назвал файлы so58176322-1.txt и so58176322-2.txt на основе идентификатора Stackoverflow для исходного сообщения.

theFiles <- list.files("./data",pattern="so5817*",full.names = TRUE)

# list the files
theFiles

Вектор theFiles содержит два имени файла.

> theFiles
[1] "./data/so58176322-1.txt" "./data/so58176322-2.txt"

Шаг 2: чтение имен столбцов из одного файла данных

Далее мы загружаем readr упаковать и извлечь строку имени столбца из первого файла в списке.

library(readr)

# read header row, add "location" and save to vector

columnData <- read_csv(theFiles[1],col_names = FALSE,n_max = 1)
columnNames <- unlist(c("location",as.vector(columnData[1,])))

Шаг 3: чтение данных и объединение в один фрейм данных

Наконец, мы будем использовать lapply() с анонимной функцией для чтения файлов данных, используя read_csv()читать данные, начиная со второго ряда. После прочтения файлов мы будем использовать do.call() с rbind(), чтобы объединить файлы в списке, сгенерированном с помощью lapply(), а затем установить имена столбцов.

# read raw data from multiple files
# 
# assume that all files have the same column names, which is inferred from OP
# 

theData <- lapply(theFiles,function(x){read_csv(theFiles[1],col_names = FALSE,skip = 1)})

# at this point, theData is a list that contains two data frames
# we can now combine the data frames with rbind() and add the column names

combinedData <- do.call(rbind,theData)
# set correct column names 
colnames(combinedData) <- columnNames
combinedData

... и вывод, показывающий правильные имена столбцов и все данные в одном фрейме данных.

> combinedData
# A tibble: 6 x 9
  location  OTU9  OTU6 OTU1972 OTU39 OTU1456 OTU16 OTU58  OTU5
  <chr>    <dbl> <dbl>   <dbl> <dbl>   <dbl> <dbl> <dbl> <dbl>
1 Soil         0     0       0     0       0     0     0     0
2 Stream       0     0       0     0       0     0     0     0
3 Unknown    100     0      20    80       0    70     0    70
4 Soil         0     0       0     0       0     0     0     0
5 Stream       0     0       0     0       0     0     0     0
6 Unknown    100     0      20    80       0    70     0    70
>

Улучшение решения: отслеживание имен файлов

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

theData <- lapply(theFiles,function(x){
  y<- read_csv(theFiles[1],col_names = FALSE,skip = 1)
  # add a column for source file name
  y$sourceFile <- x
  y})

# at this point, theData is a list that contains two data frames
# we can now combine the data frames with rbind() and add the column names

combinedData <- do.call(rbind,theData)
colnames(combinedData) <- c(columnNames,"sourceFile")
combinedData

... и вывод.

> combinedData
# A tibble: 6 x 10
  location  OTU9  OTU6 OTU1972 OTU39 OTU1456 OTU16 OTU58  OTU5 sourceFile             
  <chr>    <dbl> <dbl>   <dbl> <dbl>   <dbl> <dbl> <dbl> <dbl> <chr>                  
1 Soil         0     0       0     0       0     0     0     0 ./data/so58176322-1.txt
2 Stream       0     0       0     0       0     0     0     0 ./data/so58176322-1.txt
3 Unknown    100     0      20    80       0    70     0    70 ./data/so58176322-1.txt
4 Soil         0     0       0     0       0     0     0     0 ./data/so58176322-2.txt
5 Stream       0     0       0     0       0     0     0     0 ./data/so58176322-2.txt
6 Unknown    100     0      20    80       0    70     0    70 ./data/so58176322-2.txt
>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...