使用 fread 和 awk 对许多 .dat.gz 文件进行子集化

Subsetting many .dat.gz files using fread and awk

这是上一个 Stack Overflow 问题的延续:

我有很多 .dat.gz 文件,但此数据中的许多行都有零值,我想避免将其带入内存。

为测试用例创建数据:

# Make dir
system("mkdir practice")
require(data.table)

# Function to create data
create_write_data <- function(file.nm) {
  dt <- data.table(Day=0:365)
  dt[, (paste0("V", 1:17)) := lapply(1:17, function(x) rpois(n=366, 0.1))]
  write.table(dt, paste0("./practice/",file.nm), row.names=FALSE, sep="\t", quote=FALSE)
  system(paste0("gzip ./practice/", file.nm))    
}

这里是应用代码:

# Apply function to create 10 fake zipped data.frames (550 kb on disk)
tmp <- lapply(paste0("dt", 1:10,".dat"), function(x) create_write_data(x))

我的解决方案(无效)

之前链接的 Stack Overflow 答案为一次读取所有数据提供了这个很好的答案:

tbl = fread('cat ./practice/*dat.gz | gunzip | grep -v "^Day"')

但现在我想过滤第 14 列和第 15 列都不为 0 的数据,因此我创建了以下管道以使用 awk 命令提供给 fread

command <- "cat ./practice/*dat.gz | gunzip | awk -F, '!/^Day/ &&  !=0 &&  != 0'"
fread(command)

但是,这根本没有过滤我的数据。关于如何让 awk 命令在此工作流程中工作的任何想法?

这个问题在评论中得到了回答。

好的..它似乎适用于以下内容:
command <- "cat ./practice/*dat.gz | gunzip | awk -F, '!/^Day/' | awk ' != 0 || != 0'"
这是对数据进行 2 次传递吗?看起来它可能会减慢很多文件的速度,但它似乎确实有效。

不,这不是 2 次传递数据。它的效率很高。但是之前错过了另一个小优化:你可以进一步简化为 gunzip -c ./path/to/files*.dat.gz | awk ...