我有一个很大的.csv文件可供阅读。糟糕的是某些行已损坏,这意味着格式错误就像0.-02
而不是-0.02
这样的数字。有时甚至缺少换行符(\n
),因此两行合并为一行。
我想用read.table
读取.csv文件,并将所有colClasses
定义为我期望文件具有的格式(当然除了损坏的行)。这是一个最小的例子:
colNames <- c("date", "parA", "parB")
colClasses <- c("character", "numeric", "numeric")
inputText <- "2015-01-01;123;-0.01\n
2015-01-02;421;-0.022015-01-03;433;-0.04\n
2015-01-04;321;-0.03\n
2015-01-05;230;-0.05\n
2015-01-06;313;0.-02"
con <- textConnection(inputText, "r")
mydata <- read.table(con, sep=";", fill = T, colClasses = colClasses)
在第一个损坏的行read.table
停止并显示错误:
Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings, :
scan() expected 'a real', got '-0.022015-01-03'
有了这个错误信息,我不知道错误发生在输入的哪一行。因此,我唯一的选择是复制行-0.022015-01-03
并在文件中搜索它。但是如果你必须为很多行做这个并且总是必须重新执行read.table
直到它检测到下一个损坏行,这真的很烦人。
所以我的问题是:
read.table
告诉我发生错误的行(并可能将其保存以便进一步处理)read.table
只是跳过格式不正确的行(不是因错误而停止)?到目前为止,我尝试使用colClasses="character"
阅读所有内容,以避免首先进行格式检查。然后在我将每列转换为正确的格式时进行格式检查。然后which()
无法转换格式的所有行或结果为NA
,只删除它们。
我从一些评论中得到的想法我接下来尝试的是逐行读取输入readLine
并通过read.table
参数将结果传递给text
。如果read.table
个文件,则会通过edit()
向用户显示该行以进行更正和重新提交。这是我的代码:
con <- textConnection(inputText, "r")
mydata <- data.frame()
while(length(text <- readLines(con, n=1)) > 0){
correction = T
while(correction) {
err <- tryCatch(part <- read.table(text=text, sep=";", fill = T,
col.names = colNames,
colClasses = colClasses),
error=function(e) e)
if(inherits(err, "error")){
# try to correct this line
message(err, "\n")
text <- edit(text)
}else{
correction = F
}
}
mydata <- rbind(mydata, part)
}
如果用户进行了更正,则返回:
> mydata
date parA parB
1 2015-01-01 123 -0.01
2 2015-01-02 421 -0.02
3 2015-01-03 433 -0.04
4 2015-01-04 321 -0.03
5 2015-01-05 230 -0.05
6 2015-01-06 313 -0.02
输入文本有5行,因为缺少一个换行符。更正后的输出有6行,0.-02
更正为-0.02
。
在此解决方案中,我仍然会改变的是在读完所有内容后将所有损坏的行一起呈现以进行更正。这样,用户可以运行脚本,完成后可以立即执行所有更正。但是对于一个最小的例子,这应该足够了。
这个解决方案的真正坏处是,非常慢!处理大数据集太慢了。因此,我仍然想要使用更多标准方法或可能是特殊包装的另一种解决方案。