[仅当变量等于某个值(20Gb + csv文件)时,如何才能从csv文件中读取行

问题描述 投票:0回答:2

我有一个大约25Gb的csv文件。而且我有64GB的RAM。尽管我的ram可以处理这个大文件,但它花费的时间太长。此外,我不需要数据中的每一行。所以我想知道

  1. 如果可能仅读取第二列等于特定值的行
  2. 此外,我想知道这是否真的可以节省时间。因为我猜该软件仍会读取整个文件,然后删除不满足条件的行。

我更喜欢使用Stata。 R和python也不错。

python r csv stata
2个回答
3
投票

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方法仅将过滤后的文件加载到内存中。


2
投票

读取所有行与将整个内容实际加载到内存中的数据结构之间有区别。

在R中,vroom程序包将为各列编制索引,然后如果对第二列中的值进行过滤,它将仅读取第二列以找出何时满足条件,然后仅从中读取相关值其他列。 Read about it here

通常,像SED或AWK这样的命令行工具将非常擅长预处理数据。它们通过一次流传输文件来工作,因此整个文件永远都不会在内存中。您可以使用它来创建一个只包含您感兴趣的行的较小文件,然后使用您选择的程序正常使用它。

© www.soinside.com 2019 - 2024. All rights reserved.