R data.table fread设fill=TRUE仍提前终止读取问题求解
问题原因
fread默认会采样文件开头的数百行猜测列数、数据类型等结构信息,你的文件前175行均为7列,fread自动将预期列数固定为7,后续碰到9列的行时,即便开启fill=TRUE,也会判定列数偏差超过阈值直接终止读取,不会自动向后兼容更多列。
另外你设置sep = " "时没有开启空格清洗,文件中列之间的不定长多空格会被识别为多个空分隔符,也会干扰列数判断逻辑。
可行解决方法
按操作复杂度从低到高排列:
方法1:手动指定总列数(最简便,已知最大列数时首选)
你已经确认文件最多有9列,读取时直接通过col.names指定总列数,跳过自动猜列数逻辑,同时开启空格清洗处理多空格问题:library(data.table) dt <- fread( file = file_in, fill = TRUE, sep = " ", col.names = paste0("V", 1:9), # 显式指定共9列 strip.white = TRUE, # 自动去除字段前后空格、合并多余分隔空格 verbose = TRUE )读完后前175行的第8、9列会自动填充为
NA,后续9列的行可以正常读取。方法2:预扫描文件拿最大列数(不确定后续是否有更多列时用)
如果不确定文件后续会不会出现超过9列的行,可以先快速扫描全文件统计每行的字段数,拿到最大列数后再读取:library(data.table) # 读取全文件文本,统计每行拆分后的字段数 all_lines <- readLines(file_in, warn = FALSE) max_cols <- max(vapply( strsplit(trimws(all_lines), "\\s+"), # 按任意长度空白拆分字段 length, integer(1) )) # 按实际最大列数读取 dt <- fread( file = file_in, fill = TRUE, sep = " ", col.names = paste0("V", 1:max_cols), strip.white = TRUE ) # 清理临时对象释放内存 rm(all_lines) gc()如果文件体量极大、全量读入文本占内存过高,可以改成分块读取,每次读10万行统计列数,最终取全局最大值即可,不需要一次性加载全文件。
方法3:预处理统一分隔符后读取
可以先用命令行工具把文件里不定长的多空格替换成固定单分隔符(比如逗号),再交给fread读取,彻底避免空格分隔符的识别问题:library(data.table) # Mac/Linux直接调用awk,Windows需安装Rtools/Git Bash并配置环境变量 dt <- fread( cmd = paste0("awk '{$1=$1;print}' OFS=',' ", file_in), sep = ",", fill = TRUE )上述awk命令会把每行的连续空白替换成单个逗号,输出为标准csv格式,
fread读取时不会再出现列数判断错误。
内容的提问来源于stack exchange,提问作者melmo
相关产品推荐
相关产品推荐

