我有一个大约25Gb的csv文件。而且我有64GB的RAM。尽管我的ram可以处理这个大文件,但它花费的时间太长。此外,我不需要数据中的每一行。所以我想知道
我更喜欢使用Stata。 R和python也不错。
R的data.table::fread
对此非常有用。让我们编写一个示例文件:
library(data.table)
set.seed(39439)
NN = 3e8
DT = data.table(
ID1 = sample(LETTERS, NN, TRUE),
ID2 = sample(letters, NN, TRUE),
V1 = rnorm(NN)
)
DT
# ID1 ID2 V1
# 1: O h 0.1580064
# 2: K l -2.4281532
# 3: F z 1.7353759
# 4: B f -1.0911407
# 5: M w 0.7187998
# ---
# 299999996: D u -0.8221716
# 299999997: F f -2.4881300
# 299999998: W t 0.0371132
# 299999999: I h -1.2020380
# 300000000: L s -2.2284455
# smaller than your data, but still large
format(object.size(DT), 'Gb')
# [1] "6.7 Gb"
# write to test file
fwrite(DT, tmp <- tempfile())
# size on disk about the same
file.info(tmp)$size/1024^3
# [1] 6.191435
两个选项:(1)读取然后在R中过滤:
rm(DT)
system.time({
DT = fread(tmp)
DT = DT[ID2 == 'a']
})
# user system elapsed
# 50.390 25.662 40.004
大约40秒
((2)使用awk
进行过滤,然后阅读:
rm(DT)
system.time({
DT = fread(cmd = paste('awk -F, \'$2 == "a"\'', tmp))
})
# user system elapsed
# 350.170 3.775 354.638
后者要慢得多,因为前者是并行运行的。优点是第一种方法对内存的效率不高-在过滤到较小的表之前,您首先要占用整个文件的所有内存。 awk
方法仅将过滤后的文件加载到内存中。
读取所有行与将整个内容实际加载到内存中的数据结构之间有区别。
在R中,vroom
程序包将为各列编制索引,然后如果对第二列中的值进行过滤,它将仅读取第二列以找出何时满足条件,然后仅从中读取相关值其他列。 Read about it here。
通常,像SED或AWK这样的命令行工具将非常擅长预处理数据。它们通过一次流传输文件来工作,因此整个文件永远都不会在内存中。您可以使用它来创建一个只包含您感兴趣的行的较小文件,然后使用您选择的程序正常使用它。