在CSV文件

时间:2016-01-15 18:52:39

标签: r csv error-handling read.table corrupt-data

我有一个很大的.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直到它检测到下一个损坏行,这真的很烦人。

所以我的问题是:

  1. 有没有办法让read.table告诉我发生错误的行(并可能将其保存以便进一步处理)
  2. 有没有办法让read.table只是跳过格式不正确的行(不是因错误而停止)?
  3. 有没有人想出一种方法来在阅读过程中显示这些线以进行手动校正?我的意思是可能以普通的csv格式显示整个损坏行以进行手动校正(可能包括前后的行),然后继续读入过程,包括更正的行。
  4. 到目前为止,我尝试使用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

    在此解决方案中,我仍然会改变的是在读完所有内容后将所有损坏的行一起呈现以进行更正。这样,用户可以运行脚本,完成后可以立即执行所有更正。但是对于一个最小的例子,这应该足够了。

    这个解决方案的真正坏处是,非常慢!处理大数据集太慢了。因此,我仍然想要使用更多标准方法或可能是特殊包装的另一种解决方案。

0 个答案:

没有答案