11

我必须阅读大约 300 个单独的 CSV。我已经设法使用循环和结构化的 CSV 名称来自动化这个过程。然而,每个 CSV 在开始时都有 14-17 行垃圾,并且随机变化,因此在 read.table 命令中硬编码“跳过”参数将不起作用。每个 CSV 的列名和列数相同。

这是我所反对的一个例子:

QUICK STATISTICS:

      Directory: Data,,,,
           File: Final_Comp_Zn_1
      Selection: SEL{Ox*1000+Doma=1201}
         Weight: None,,,
     ,,Variable: AG,,,

Total Number of Samples: 450212  Number of Selected Samples: 277


Statistics

VARIABLE,Min slice Y(m),Max slice Y(m),Count,Minimum,Maximum,Mean,Std.Dev.,Variance,Total Samples in Domain,Active Samples in Domain AG,  
6780.00,   6840.00,         7,    3.0000,   52.5000,   23.4143,   16.8507,  283.9469,        10,        10 AG,   
6840.00,   6900.00,         4,    4.0000,    5.5000,    4.9500,    0.5766,    0.3325,        13,        13 AG,   
6900.00,   6960.00,        16,    1.0000,   37.0000,    8.7625,    9.0047,   81.0848,        29,        29 AG,   
6960.00,   7020.00,        58,    3.0000,   73.5000,   10.6931,   11.9087,  141.8172,       132,       132 AG,   
7020.00,   7080.00,        23,    3.0000,  104.5000,   15.3435,   23.2233,  539.3207,        23,        23 AG,   
7080.00,   7140.00,        33,    1.0000,   15.4000,    3.8152,    2.8441,    8.0892,        35,        35 AG,

基本上我想从行中读取VARIABLE,Min slice Y(m),Max slice Y(m),...。我可以想到一些解决方案,但我不知道如何对其进行编程。无论如何我可以:

  1. 首先阅读 CSV 并以某种方式计算出有多少行垃圾,然后重新阅读并指定要跳过的正确行数?或者
  2. 告诉read.table它在找到列名时开始阅读(因为这些对于每个 CSV 都是相同的)并忽略之前的所有内容?

我认为解决方案(2)是最合适的,但我愿意接受任何建议!

4

2 回答 2

17

这是可以采用的一种方法的最小示例。

首先,让我们组成一些类似于您描述的 csv 文件:

cat("blah\nblah\nblah\nVARIABLE,X1,X2\nA,1,2\n", file="myfile1.csv")
cat("blah\nVARIABLE,A1,A2\nA,1,2\n", file="myfile2.csv")
cat("blah\nblah\nVARIABLE,Z1,Z2\nA,1,2\n", file="myfile3.csv")

其次,确定数据从哪里开始:

linesToSkip <- sapply(list.files(pattern = "myfile.*.csv"), 
                      function(x) grep("^VARIABLE", readLines(x))-1)

第三,使用该信息将文件读入单个列表。

lapply(names(linesToSkip), 
       function(x) read.csv(file=x, skip = linesToSkip[x]))
# [[1]]
#   VARIABLE X1 X2
# 1        A  1  2
# 
# [[2]]
#   VARIABLE A1 A2
# 1        A  1  2
# 
# [[3]]
#   VARIABLE Z1 Z2
# 1        A  1  2

编辑#1

读取数据两次的另一种方法是将其读取一次到列表中,然后执行相同类型的处理:

myRawData <- lapply(list.files(pattern = "myfile.*.csv"), readLines)
lapply(myRawData, function(x) {
  linesToSkip <- grep("^VARIABLE", x)-1
  read.csv(text = x, skip = linesToSkip)
})

或者,就此而言:

lapply(list.files(pattern = "myfile.*.csv"), function(x) {
  temp <- readLines(x)
  linesToSkip <- grep("^VARIABLE", temp)-1
  read.csv(text = temp, skip = linesToSkip)
})

编辑#2

正如@PaulHiemstra 所指出的,您可以使用该参数n仅将每个文件的几行读入内存,而不是读取整个文件。因此,如果您确定每个文件中的“垃圾”行不超过 20 行,如果您使用的是所描述的第一种方法,则可以使用:

linesToSkip <- sapply(list.files(pattern = "myfile.*.csv"), 
                      function(x) grep("^VARIABLE", readLines(x, n = 20))-1)
于 2013-03-11T06:26:26.950 回答
9

freaddata.table中的函数自动检测要跳过的行数。该功能目前处于开发阶段。

这是一个示例代码:

require(data.table)

cat("blah\nblah\nblah\nVARIABLE,X1,X2\nA,1,2\n", file="myfile1.csv")
cat("blah\nVARIABLE,A1,A2\nA,1,2\n", file="myfile2.csv")
cat("blah\nblah\nVARIABLE,Z1,Z2\nA,1,2\n", file="myfile3.csv")

lapply(list.files(pattern = "myfile.*.csv"), fread)
于 2013-03-11T07:52:06.520 回答