读取 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>>
有什么技巧可以建议您读取文件的所有行吗?
假设我们有一个这样的文本文件 "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
对出现在中间而不是开头的额外列很挑剔,所以这就是为什么使用 select
和 fill
在这里不起作用。您可以做的是预先获取它为您提供的所有行,然后在您已经加载的行上使用 skip
重试。在第二次(或更多次)尝试中,额外的列现在将位于开头,因此 fill
和 select
将按预期工作。可能有更优雅的方法来执行以下操作,但这有效
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)
我正在尝试读取默认情况下应该有 7 列的文件,但可能在某些字符串中可能有一些逗号导致其他行有超过 7 列。
不管其他专栏中有哪些信息,我唯一的目标是阅读前 7 列。但是,即使在添加参数 select = 1:7
> 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>>
有什么技巧可以建议您读取文件的所有行吗?
假设我们有一个这样的文本文件 "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
对出现在中间而不是开头的额外列很挑剔,所以这就是为什么使用 select
和 fill
在这里不起作用。您可以做的是预先获取它为您提供的所有行,然后在您已经加载的行上使用 skip
重试。在第二次(或更多次)尝试中,额外的列现在将位于开头,因此 fill
和 select
将按预期工作。可能有更优雅的方法来执行以下操作,但这有效
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)