绕过"鬼" data.table :: fread中的换行符或结尾文件(EOF)

时间:2015-09-30 16:40:01

标签: r error-handling dataframe data.table

我使用data.table::fread将从(可访问的)数据库导出的几个大的制表符分隔文本文件加载到R中。 fread可以轻松快捷地处理大多数文件,但其中一个文件会生成定期报告的fread错误:

Error in fread(read_problem, encoding = "UTF-8", na.strings = "", header = TRUE,  : 
                   Expected sep ('  ') but new line or EOF ends field ...

此处提供了包含违规行的较小(2000行)版本的文件(RDS file)。

以下是我尝试诊断问题的方法:

library(data.table) # I'm using 1.9.7 development (same error with 1.9.6)
read_problem <- readRDS("read_problem.rds")
error <- fread(read_problem, encoding = "UTF-8", na.strings = "",
               header = TRUE, sep = "\t", 
               colClasses = rep("character", 44),  # For simplicity
               verbose = TRUE)

如果我删除违规行,问题就会消失:

cat(read_problem, file = "temp")   
string_vec <- readLines("temp")
clipped_vec <- string_vec[-1027] # Get rid of problem line 1027
restored <- paste(clipped_vec, collapse = "\n")
noerror <- fread(restored, encoding = "UTF-8", na.strings = "",
                 header = TRUE, sep = "\t", 
                 colClasses = rep("character", 44)) # For simplicity
class(noerror)
[1] "data.table" "data.frame"

dim(noerror) 
[1] 1999   44

错误消息似乎很清楚:fread正在寻找&#34; \ t&#34;但是找到了其他的东西。

但是,通过仔细查看相对于周围人的违规行,我发现没有什么明显的。

制表符的数量相同

sapply(gregexpr("\t", string_vec[1026:1028]), length)
[1] 43 43 43

换行信息似乎相同

unlist(gregexpr("\n", string_vec[1026:1028]))
[1] -1 -1 -1

以下是将违规行本身视为字符串:

string_vec[1027]
[1] "URN:CornellLabOfOrnithology:EBIRD:OBS132960387\t29816\tspecies\tNelson's Sparrow\tAmmodramus nelsoni\t\t\t1\t\t\tUnited States\tUS\tGeorgia\tUS-GA\tGlynn\tUS-GA-127\tUS-GA_3181\t\t\tJekyll Island\tL140461\tH\t31.0464993\t-81.4113007\t1990-11-03\t13:15:00\t\"Jekyll Island and Causeway. Partly cloudy, mild, NE wind 8-15 mph. Note: Did very little birding in upland habitats as time available was rather brief.\"  Data entered on behalf of Paul Sykes by Alison Huff (arhuff@uga.edu) on 12-15-11.\tListed on old Georgia Field Checklist as \"Sparrow, Sharp-tailed.\"\tobsr289931\tPaul\tSykes\tS9336358\teBird - Traveling Count\tEBIRD\t270\t8.047\t\t1\t1\t\t1\t0\t\t"

如果没有手动提取违规行,是否有任何建议可以解决这个问题?

3 个答案:

答案 0 :(得分:6)

使用this commit,现在已在当前开发版本v1.9.7中修复。因此,下一个稳定版本应该能够使用quote=""正确阅读。

require(data.table) #v1.9.7+
fread('"abcd efgh." ijkl.\tmnop "qrst uvwx."\t45\n', quote="")
#                    V1                V2 V3
# 1: "abcd efgh." ijkl. mnop "qrst uvwx." 45

在第1027行,"Sparrow, Sharp-tailed."末尾只有一个标签。在其他行中,在该字段之后,在“obsr [0-9]”字段开始之前有两个。

选项卡的数量似乎匹配,因为在第1027行,“在旧的Georgia Field上列出”而不是空格之前有一个标签..

因此,1027行只获得43个cols而不是44.这似乎是个问题。

再看一遍,好像Listed on old Georgia Field Checklist as "Sparrow, Sharp-tailed."应该作为一个单独的列阅读,而是与前一列一起阅读......

这是一个较小的可重复的例子:

# note that there are only 2 instead of 3 columns
fread('"abcd efgh." ijkl.\tmnop "qrst uvwx."\t45\n')
#                                     V1 V2
# 1: abcd efgh." ijkl.\tmnop "qrst uvwx. 45

# add a header column and it returns the same error
fread('a\tb\tc\n"abcd efgh." ijkl.\tmnop "qrst uvwx."\t45\n')
# Error in fread("a\tb\tc\n\"abcd efgh.\" ijkl.\tmnop \"qrst uvwx.\"\t45\n") : 
#   Expected sep (' ') but new line, EOF (or other non printing character) 
#   ends field 1 when detecting types (   first): "abcd efgh." ijkl.    mnop 
#   "qrst uvwx."    45

提起1367

答案 1 :(得分:0)

一种可能的解决方案是:

  1. 将所有CSV读入一个列表

    df&lt; -lapply(csv,function(x)read.csv(x,stringsAsFactors = FALSE))

  2. 列表中的每个元素代表一个CSV

    1. 将列表转换为一个大数据框
    2. df2&lt; - ldply(df,data.frame)

      1. 像往常一样使用grep删除包含EOF的行。
      2. df3&lt; -df2 [!grepl(&#34; eof&#34;,df2 $ V1),]

        其中V1是EOF所在的列名。

答案 2 :(得分:0)

对于以下错误:“预期的sep('|'),但是在读取数据时,新行或EOF在第8863行的字段6结束了:”

您只需要在fread代码中添加其他quote =“”

fread(load_file_from_directory,sep =“ |”,quote =“”)