使用R从目录读取.txt文件

时间:2019-09-30 23:14:48

标签: r

我试图从目录中读取文本文件,然后将这些文件中的数据合并到1个数据框中。文件为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

这是我第一次尝试在R中进行for循环或读取文件目录,因此许多错误对我来说都是新的。

我的另一个问题是,是否可以一次从每个文件中读取一行,并为3个不同的行创建3个不同的文件。但是,我什至不知道从哪里开始。

希望这个问题看起来很像。

谢谢! 科琳

1 个答案:

答案 0 :(得分:0)

有两个要解决的问题。首先,我们需要读取一组具有相同列的文件,这些文件存储在文件扩展名为.txt的子目录中。数据文件中的列由分隔符分隔,分隔符的值未在OP中指定。

第二,每个文件都缺少列标题,该列标题似乎是名为locationtype的列。

第二个考虑因素使得很难使用标准R函数来读取文件,因为如果要使用以下方式处理文件,则大多数原始数据文件读取器函数都希望原始数据文件中每一列的列名都为header = TRUE参数。

我们将使用readr::read_csv()函数来解决此问题,因为readr::read_csv()允许我们指定要从数据文件读取的行。

具体来说,我们将从一个文件中读取列名,添加一个location列名,然后读取整个数据文件集以避免使用第一行,并且不将第一行设置为列名。

我们复制了帖子中的数据,并将其两个副本保存到当前R工作目录的\data子目录中的数据文件中。我们使用,作为分隔符,以使其在示例数据中可见。

数据如下:

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:从子目录中检索文件名

我根据原始帖子的Stackoverflow标识符为文件so58176322-1.txtso58176322-2.txt命名。

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
>