读取 R 中列数不固定的文件 fread()

Reading a file that has non fixed number of columns fread() in R

我正在尝试读取默认情况下应该有 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

假设我们有一个这样的文本文件 "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")

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 列显示在更下方,那么这将适用于这些情况。

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)