读取包含可变行的CSV以跳过批量

时间:2014-04-26 00:29:34

标签: r

我正在尝试创建一个循环,读取多个CSV文件,这些文件都具有相同类型的气温数据。但是,我想在数据上方跳过行。这些是"警报"在数据集中。每个文件可能具有不同数量的警报,因此要跳过不同的行数。见下文:

-------------First CSV file---------------
Logger 001
Alarm 1
Alarm 2
Alarm 3
Alarm 4
Date, Temp
01/01/2011, -1.2
01/02/2011, -1.3
01/03/2011, -1.1
01/04/2011, -1.2

-------------Second CSV file---------------
Logger 001
Alarm 1
Alarm 2
Alarm 3
Alarm 4
Alarm 5
Alarm 6
Alarm 7
Date, Temp
01/01/2011, -1.2
01/02/2011, -1.3
01/03/2011, -1.1
01/04/2011, -1.2

如何获取DateTemp的索引告诉read.csv跳到该行?

for (i in 1:length(csv.list))  {
  df = read.csv(csv.list[i], header = T, skip=????????)
}

4 个答案:

答案 0 :(得分:2)

您可以在循环中的read.table之前添加几行

使用readLines读取数据

r <- readLines(textConnection("Logger 001
               Alarm 1
               Alarm 2
               Alarm 3
               Alarm 4
               Date, Temp
               01/01/2011, -1.2
               01/02/2011, -1.3
               01/03/2011, -1.1
               01/04/2011, -1.2"))

[但没有textConnection,即r <- readLines("yourcsv")]

使用grep

查找实际标题开头的行号
dt <- grep("Date",r)

读入您的数据 - 跳过标题之前的行

read.table(text=r , header=TRUE, sep="," , skip = dt-1)


因此,要读入多个csv文件 - 这些文件将存储在数据列表中,帧

 df.lst <- lapply(csv.list , function(i) {
                        r <- readLines(i)
                        dt <- grep("Date",r)
                        read.table(text=r , header=TRUE, sep="," , skip = dt-1)
                         })

答案 1 :(得分:2)

来自“data.table”包的

fread可能对您有用,因为它非常适合自动检测“垃圾”标题行。这是一个例子:

首先,创建两个示例csv文件

cat("Logger 001
Alarm 1
Alarm 2
Alarm 3
Alarm 4
Date, Temp
01/01/2011, -1.2
01/02/2011, -1.3
01/03/2011, -1.1
01/04/2011, -1.2
", file = "socsv1.csv", sep = "\n")

cat("Logger 001
Alarm 1
Alarm 2
Alarm 3
Alarm 4
Alarm 5
Alarm 6
Alarm 7
Date, Temp
01/01/2011, -1.2
01/02/2011, -1.3
01/03/2011, -1.1
01/04/2011, -1.2", file = "socsv2.csv", sep = "\n")

## Check that they were created
list.files(pattern = "socsv")
# [1] "socsv1.csv" "socsv2.csv"

现在,只需使用fread并指定sep,而不是让fread猜测。

library(data.table)
lapply(list.files(pattern = "socsv"), fread, sep = ",")
# [[1]]
#          Date  Temp
# 1: 01/01/2011  -1.2
# 2: 01/02/2011  -1.3
# 3: 01/03/2011  -1.1
# 4: 01/04/2011  -1.2
# 
# [[2]]
#          Date  Temp
# 1: 01/01/2011  -1.2
# 2: 01/02/2011  -1.3
# 3: 01/03/2011  -1.1
# 4: 01/04/2011  -1.2

答案 2 :(得分:1)

count.fields可以识别每个文件的第一行,其中包含两个以逗号分隔的字段。然后,您可以使用它来指定skip。例如:

writeLines('Logger 001
Alarm 1
Alarm 2
Alarm 3
Alarm 4
Date, Temp
01/01/2011, -1.2
01/02/2011, -1.3
01/03/2011, -1.1
01/04/2011, -1.2', f <- tempfile())

writeLines('Logger 001
Alarm 1
Alarm 2
Alarm 3
Alarm 4
Alarm 5
Alarm 6
Alarm 7
Date, Temp
01/01/2011, -1.2
01/02/2011, -1.3
01/03/2011, -1.1
01/04/2011, -1.2', f2 <- tempfile())

for (x in c(f, f2))  {
  ind <- match(2, count.fields(x, ','))
  df <- read.csv(x, header = T, skip=ind - 1)
  print(df)
}

#         Date Temp
# 1 01/01/2011 -1.2
# 2 01/02/2011 -1.3
# 3 01/03/2011 -1.1
# 4 01/04/2011 -1.2
# Date Temp
# 1 01/01/2011 -1.2
# 2 01/02/2011 -1.3
# 3 01/03/2011 -1.1
# 4 01/04/2011 -1.2

答案 3 :(得分:0)

我认为有一种更简单的方法,就是通过一些选项来读取文件。

df = read.csv('weather-logger2.csv', colClasses = c('character', 'numeric'),
              col.names = c('Date', 'Temp'),
              na.strings = 'Temp', fill = TRUE, stringsAsFactors = FALSE)

前几行包含不是日期的字符串,当你将它们转换为日期时会给出NA(你无论如何都必须转换这种方式进行进一步处理),然后你只需要去掉缺失的值:

     Date Temp
1     Alarm 1   NA
2     Alarm 2   NA
3     Alarm 3   NA
4     Alarm 4   NA
5     Alarm 5   NA
6     Alarm 6   NA
7     Alarm 7   NA
8        Date   NA
9  01/01/2011 -1.2
10 01/02/2011 -1.3
11 01/03/2011 -1.1
12 01/04/2011 -1.2

df$Date = as.Date(df$Date, '%d/%m/%Y')
df = subset(df, !is.na(Date))

得到:

         Date Temp
9  2011-01-01 -1.2
10 2011-02-01 -1.3
11 2011-03-01 -1.1
12 2011-04-01 -1.2