【问题标题】:r - Error: Text after processing all cols in fread (data.table)r - 错误:处理 fread (data.table) 中的所有列后的文本
【发布时间】:2017-11-26 14:44:15
【问题描述】:

我尝试在 R (3.4.0) 中导入 text file,它实际上包含 4 列,但第 4 列大部分是空的,直到第 200,000+ 行。我使用包 data.table 中的 fread() (ver 1.10.4)

fread("test.txt",fill = TRUE, sep = "\t", quote = "", header = FALSE)

我收到此错误消息:

Error in fread("test.txt", fill = TRUE, sep = "\t", quote = "", header = FALSE) : 
Expecting 3 cols, but line 258088 contains text after processing all cols. Try again with fill=TRUE. Another reason could be that fread's logic in distinguishing one or more fields having embedded sep='  ' and/or (unescaped) '\n' characters within unbalanced unescaped quotes has failed. If quote='' doesn't help, please file an issue to figure out if the logic could be improved.

我检查了文件,在第 4 列的第 258088 行 (“8-4”) 中有附加文本。

尽管如此,fill = TRUE 并没有像我预期的那样解决这个问题。我认为可能是 fread() 不恰当地确定列号,因为附加列在文件中出现得很晚。所以我尝试了这个:

fread("test.txt", fill = TRUE, header = FALSE, sep = "\t", skip = 250000)

错误仍然存​​在。另一方面,

fread("test.txt", fill = TRUE, header = FALSE, sep = "\t", skip = 258080)

这没有错误。

我以为我找到了原因,但是当我使用以下生成的dummy file 进行测试时发生了奇怪的事情:

write.table(matrix(c(1:990000), nrow = 330000), "test2.txt", sep = "\t", row.names = FALSE)

在 Excel 的第 250000 行的第 4 列中添加了“8-4”。当被 fread() 读取时:

fread("test2.txt", fill = TRUE, header = FALSE, sep = "\t")

它工作正常,没有错误消息,这应该表明一些延迟的附加列不一定会触发错误。

我还尝试更改编码(“Latin-1”和“UTF-8”)或引用,但都没有帮助。

现在我感到一头雾水,希望我能用可重复的信息做足功课。感谢您的帮助。

有关其他环境信息,我的 sessionInfo() 是:

R version 3.4.0 (2017-04-21)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Sierra 10.12.5

Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib

locale:
[1] zh_TW.UTF-8/zh_TW.UTF-8/zh_TW.UTF-8/C/zh_TW.UTF-8/zh_TW.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
  [1] dplyr_0.5.0            purrr_0.2.2.2          readr_1.1.1            tidyr_0.6.3           
  [5] tibble_1.3.3           ggplot2_2.2.1          tidyverse_1.1.1        stringr_1.2.0         
  [9] microbenchmark_1.4-2.1 data.table_1.10.4     

loaded via a namespace (and not attached):
[1] Rcpp_0.12.11     cellranger_1.1.0 compiler_3.4.0   plyr_1.8.4       forcats_0.2.0   
[6] tools_3.4.0      jsonlite_1.5     lubridate_1.6.0  nlme_3.1-131     gtable_0.2.0    
[11] lattice_0.20-35  rlang_0.1.1      psych_1.7.5      DBI_0.6-1        parallel_3.4.0  
[16] haven_1.0.0      xml2_1.1.1       httr_1.2.1       hms_0.3          grid_3.4.0      
[21] R6_2.2.1         readxl_1.0.0     foreign_0.8-68   reshape2_1.4.2   modelr_0.1.0    
[26] magrittr_1.5     scales_0.4.1     rvest_0.3.2      assertthat_0.2.0 mnormt_1.5-5    
[31] colorspace_1.3-2 stringi_1.1.5    lazyeval_0.2.0   munsell_0.4.3    broom_0.4.2     

【问题讨论】:

  • 我认为解决此问题的最简单方法是在文件顶部添加标题,标题由文件中的制表符分隔。 fread 默认查看数据的前 30 行,并使用它来推断它有多少列,因此在第 4 列中没有这些行的数据,它假定只有 3 个字段。
  • 或许加quote=""
  • 我猜这不是freadread.csv 的问题。文件有问题。 csv 的每一行应该有相同的列数,而您的文件没有。您应该处理生成文件的过程,而不是如何导入它。
  • 感谢您的所有建议。我试图在那里添加一个标题,它确实有效。尽管如此,我正在处理一堆这样的文件,所以我想知道是否有一些通用的解决方案。我知道第一个文件的格式很尴尬,而且由于它是我们分析器的标准导出,所以没有太多选择。我可以先解决格式问题,但由于read.table()fill = TRUE 一起工作正常,所以离开它并返回read.table() 会更快。当我转向 fread() 时,我正在寻找一种更快的方式来安排这些

标签: r data.table


【解决方案1】:

实际上您提供的两个文件之间存在差异,我认为这是导致 fread 输出不同的原因。

第一个文件在第 3 列之后有一个行尾,但第 258088 行除外,其中第 4 列有一个制表符,然后是行尾。 (您可以使用选项“显示所有字符以确认”)。

另一方面,第二个文件在所有行中都有一个额外的选项卡,即一个新的空列。 所以在第一种情况下, fread 需要 3 列,然后找到第 4 列。相反,在第二个文件中, fread 需要 4 列。

我用fill=TRUE 检查了 read.table,它对这两个文件都有效。所以我认为使用 fread 的 fill 选项会有所不同。

我希望从fill=TRUE 开始,所有行都将用于推断列数(计算时间成本)。

在 cmets 中,您可以使用一些不错的解决方法。

【讨论】:

  • 感谢您的洞察!我没有注意到区别。我猜 Excel 可能会添加额外的选项卡,而第一个示例文件是由我们的分析器生成的。 read.table()fill = TRUE 完美地完成了它的工作,而我尝试 fread() 的原因是我们有很多这些要运行,更快的导入会很有帮助。
  • 不客气!我认为添加标题并使用 fread 会有所回报,因为正如您所说,您有很多文件并且您使用 read.table 很多...
【解决方案2】:

文件有问题:如果表格有四列,则在每行的末尾,第四列缺少 \t 应该已经存在。

在这种情况下,使用低级方法可能会更好:逐行读取文件,将\t 添加到没有第四列的每一行,用\t 分割每一行,然后在data.frame 中收集所有内容。以上大部分工作都是由data.table::tstrsplit 函数完成的。尝试类似:

f<-readLines("test.txt")
require(stringr)
require(data.table)
a<-data.frame(tstrsplit(f,"\t",type.convert=TRUE,names=TRUE,keep=1:4),stringsAsFactors=FALSE)
str(a)
#'data.frame':  273070 obs. of  4 variables:
# $ V1: num  0 0.002 0.004 0.006 0.008 0.01 0.012 0.014 0.016 0.018 ...
# $ V2: num  -18.7113 -1.2685 0.0768 0.1507 0.1609 ...
# $ V3: num  0 0 0 0 0 0 0 0 0 0 ...
# $ V4: chr  NA NA NA NA ...

【讨论】:

    【解决方案3】:

    我也在为此苦苦挣扎。我在这里How can you read a CSV file in R with different number of columns 找到了另一个解决方案(用于csv 和read.table)。这个答案您可以使用方便的函数count.fields 逐行计算文件的分隔符,然后获取最大字段数将最大列名数传递给fread。下面是一个可重现的示例。

    生成具有奇数字段的文本

    text <- "12223, University\n12227, bridge, Sky\n12828, Sunset\n13801, Ground\n14853, Tranceamerica\n16520, California, ocean, summer, golden gate, beach, San Francisco\n14854, San Francisco\n15595, shibuya, Shrine\n16126, fog, San Francisco\n"
    

    写入文件

    cat(text, file = "foo")
    

    扫描文件以查找分隔符

    max.fields<-max(count.fields("foo", sep = ','))
    

    现在使用fread 读取文件,但期望 col.names 参数的最大列数

    fread("foo", header = FALSE, fill=TRUE, sep=",", col.names = paste("V", 1:max.fields, sep = ""))
    

    但是,我将此数据基于来自 ?count.fields 的示例数据,发现如果最大字段数在文件的最后一行,fread 仍然会失败并出现以下错误。

    fread("foo", header = FALSE, fill = TRUE, sep = ",", col.names = paste("V", : 预期 3 列,但第 9 行包含处理所有列后的文本。使用 fill=TRUE 再试一次。另一个原因可能是 fread 在区分一个或多个在不平衡的非转义引号内嵌入了 sep=',' 和/或(非转义的)'\n' 字符的字段的逻辑失败了。如果 quote='' 没有帮助,请提交问题以确定是否可以改进逻辑。

    例子

    text <- "12223, University\n12227, bridge, Sky\n12828, Sunset\n13801, Ground\n14853, Tranceamerica\n14854, San Francisco\n15595, shibuya, Shrine\n16126, fog, San Francisco\n16520, California, ocean, summer, golden gate, beach, San Francisco\n"
    cat(text, file = "foo")
    max.fields<-max(count.fields("foo", sep = ','))
    fread("foo", header = FALSE, fill=TRUE, sep=",", col.names = paste("V", 1:max.fields, sep = ""))
    

    我会将此问题报告给data.table Github。更新:这里记录的问题https://github.com/Rdatatable/data.table/issues/2691

    【讨论】:

      猜你喜欢
      • 2015-12-30
      • 2014-10-28
      • 1970-01-01
      • 1970-01-01
      • 2018-02-11
      • 2023-03-06
      • 2016-08-02
      • 2015-10-23
      • 2014-09-06
      相关资源
      最近更新 更多