【问题标题】:Reading a file that has non fixed number of columns fread() in R读取 R 中列数不固定的文件 fread()
【发布时间】:2022-01-13 12:24:14
【问题描述】:

我正在尝试读取默认情况下应该有 7 列的文件,但可能在某些字符串中可能有一些逗号导致其他行有超过 7 列。 不管其他列中有哪些信息,我唯一的目标是阅读前 7 列。但是,即使添加了参数select = 1:7,fread 也不会读取整个文件

> data <- fread("dpp.DAT",header=FALSE, fill=T, select = 1:7, sep=", ",stringsAsFactors = F)
Warning message:
In fread("dpp.DAT", header = FALSE, fill=T, select = 1:7,sep = ",", stringsAsFactors = F) :
  Stopped early on line 45922. Expected 7 fields but found 8. Consider fill=TRUE and comment.char=. First discarded non-empty line: <<84172666,DS,BRAND 4 - DERIVATIVE,#PL LOC BDD  :  BDD - BRAND 3 - DERIVATIVE,37324,BLEND-A-MD-INSPRD-BY-NTR-SGHH,BLEND B MAR INSPIRED BY OTHER CHAMOMILE, VAG + HHHH>>

您可以建议读取文件的所有行吗?

Sample dataset

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    Dean 的回答提供了比我更多的自动化。每当我遇到这个问题(实际上可能是格式不正确的数据)时,我都会求助于手动查找然后使用 rbind 重建提取:

    s1 <- fread("Extract.txt",
        nrows=674170,
        strip.white = TRUE,
        fill = TRUE,
        blank.lines.skip = TRUE,
        encoding="UTF-8")
    
    s2 <- fread("Extract.txt",
        strip.white = TRUE,
        fill = TRUE,
        blank.lines.skip = TRUE,
        skip=674170,
        encoding="UTF-8")
    # ad.infinitum until you complete "Extract.txt"
    s3 <- rbind(s1,s2)
    rm(s1)
    rm(s2)
    

    【讨论】:

      【解决方案2】:

      data.table 对出现在中间而不是开头的额外列很挑剔,这就是为什么在这里使用 selectfill 不起作用的原因。你可以做的是把它给你的所有行放在前面,然后在你已经加载的行上再试一次skip。在第二次(或更多)尝试中,额外的列现在将位于开头,因此 fillselect 按预期工作。可能有更优雅的方法来执行以下操作,但这有效

      library(data.table)
      
      #capture warnings so we can evaluate what happened last in code
      tempfile='tmp321364.txt' 
      conn<-file(tempfile, open="r+")
      sink(file=conn, type='message')
      
      DT<-list()
      while(TRUE) {
        DT[[length(DT)+1]] <- fread(filename, header=FALSE,stringsAsFactors = F, fill=T, select=1:7, skip=ifelse(length(DT)>0,sum(sapply(DT, nrow)),0))
        if(nrow(DT[[length(DT)]])==0) break
        warns<-readLines(conn)
        if(length(warns)==3) { #The warning about extra columns is 3 lines long
          DT[[length(DT)+1]]<-  fread(filename, header=FALSE,stringsAsFactors = F, fill=T, select=1:7, skip=sum(sapply(DT, nrow)))
          if(nrow(DT[[length(DT)]])==0) break
        } else { #an error about skipping too many rows is not 3 lines, assuming away other issues
          break
        }
      }
      DT<-rbindlist(DT)
      sink(NULL, type='message')
      close(conn)
      rm(tempfile)
      

      使用您的确切数据,您不需要 while(TRUE) 循环,但例如,如果有第 10 列显示在更下方,那么这将适用于这些情况。

      【讨论】:

        【解决方案3】:

        假设我们有一个文本文件"test.txt",如下所示:

        a,b,c
        d,e,f
        g,h,i,j
        k,l,m
        

        我们可以读入并设置FILL=T,然后将最后一列子集化出来:

        > fread("test.txt", fill=T)[,-4]
           V1 V2 V3
        1:  a  b  c
        2:  d  e  f
        3:  g  h  i
        4:  k  l  m
        

        或者,设置select=1:3:

        > fread("test.txt", fill=T, select = 1:3)
           V1 V2 V3
        1:  a  b  c
        2:  d  e  f
        3:  g  h  i
        4:  k  l  m
        

        编辑

        解决方案是这样使用cut unix 命令:

        terminal$ cut Test_Fread_column.DAT -d',' -f1-7 > tmp
        R> fread("tmp")
        

        【讨论】:

        • 我忘了在问题中提及,但我已经尝试提供参数fill=T 但我仍然遇到同样的错误
        • @Macosso 除非您提供数据样本,否则这可能很难解决。你能发布一个减少的数据子集,包括违规行吗?
        • 可以使用下面的数据集来测试github.com/Macosso/Test_R_fread
        • 好的。只做cut Test_Fread_column.DAT -d',' -f1-7 &gt; tmp(在unix shell 中)然后fread("tmp") 更容易,效果很好。
        • 您能否使用此命令更新您的答案,以便获得批准。如果你有的话,你也可以分享一下windows CMD的命令吗?
        猜你喜欢
        • 2019-10-13
        • 2016-10-10
        • 2015-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多