首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在package data.table中使用fread一次读取数据块

在package data.table中使用fread一次读取数据块
EN

Stack Overflow用户
提问于 2013-11-11 03:38:43
回答 3查看 8.6K关注 0票数 30

我正在尝试使用data.table包中的fread函数输入一个以制表符分隔的大文件(大约2 2GB)。但是,因为它太大了,所以不能完全放入内存。我尝试通过使用skipnrow参数来分块输入,如下所示:

代码语言:javascript
复制
chunk.size = 1e6
done = FALSE
chunk = 1
while(!done)
{
    temp = fread("myfile.txt",skip=(chunk-1)*chunk.size,nrow=chunk.size-1)
    #do something to temp
    chunk = chunk + 1
    if(nrow(temp)<2) done = TRUE
}

在上面的例子中,我一次读取一百万行,对它们执行计算,然后得到下一百万行,依此类推。这段代码的问题是,在检索到每个块之后,fread需要从最开始开始扫描文件,因为在每次循环迭代之后,skip会增加一百万。因此,在每个块之后,fread需要越来越长的时间才能真正到达下一个块,这使得效率非常低。

有没有一种方法可以告诉fread每100万行暂停一次,然后从这一点继续阅读,而不需要从头开始?有任何解决方案吗,或者这应该是一个新的功能请求?

EN

回答 3

Stack Overflow用户

发布于 2014-12-18 05:17:53

您应该使用LaF包。这在数据上引入了一种指针,从而避免了-对于非常大的数据-读取整个文件的恼人行为。据我所知,data.table pckg中的fread()需要知道总行数,这对于GB数据来说需要时间。使用LaF中的指针,您可以转到您想要的每一行;并读取您可以应用函数的数据块,然后移动到下一个数据块。在我的小PC上,我以10e6行的步长运行了一个25 GB的csv文件,提取了总共需要的~5e6个观察值--每个10e6块需要30秒。

更新:

代码语言:javascript
复制
library('LaF')
huge_file <- 'C:/datasets/protein.links.v9.1.txt'

#First detect a data model for your file:
model <- detect_dm_csv(huge_file, sep=" ", header=TRUE)

然后使用模型创建到文件的连接:

代码语言:javascript
复制
df.laf <- laf_open(model)

一旦完成,你就可以做所有的事情,而不需要知道文件的大小,就像在data.table中一样。例如,将指针放到第100e6行,并从此处读取1e6行数据:

代码语言:javascript
复制
goto(df.laf, 100e6)
data <- next_block(df.laf,nrows=1e6)

现在data包含了CSV文件的1e6行(从100e6行开始)。

您可以读取数据块(大小取决于您的内存),并且只保留您需要的内容。例如,我的例子中的huge_file指向一个包含所有已知蛋白质序列的文件,其大小>27 GB -对于我的PC来说,这是一个很大的文件。为了只得到人类序列,我使用有机体id进行了过滤,对于人来说,它是9606,它应该出现在变量protein1的开头。一种糟糕的方法是将其放入一个简单的for循环中,然后一次只读取一个数据块:

代码语言:javascript
复制
library('dplyr')
library('stringr')

res <- df.laf[1,][0,]
for(i in 1:10){
  raw <-
    next_block(df.laf,nrows=100e6) %>% 
    filter(str_detect(protein1,"^9606\\."))
  res <- rbind(res, raw)

    }

现在res包含了过滤后的人类数据。但更好的是,对于更复杂的操作,例如对数据的即时计算,函数process_blocks()将参数作为函数。因此,在函数中,您可以对每段数据做任何您想做的事情。请阅读文档。

票数 21
EN

Stack Overflow用户

发布于 2017-05-02 17:53:58

您可以使用readr的read_*_chunked读取数据,例如按块过滤数据。有关示例,请参阅herehere

代码语言:javascript
复制
# Cars with 3 gears
f <- function(x, pos) subset(x, gear == 3)
read_csv_chunked(readr_example("mtcars.csv"), DataFrameCallback$new(f), chunk_size = 5)
票数 10
EN

Stack Overflow用户

发布于 2018-03-01 23:01:35

一个相关的选项是chunked包。下面是一个3.5 GB文本文件的示例:

代码语言:javascript
复制
library(chunked)
library(tidyverse)

# I want to look at the daily page views of Wikipedia articles
# before 2015... I can get zipped log files
# from here: hhttps://dumps.wikimedia.org/other/pagecounts-ez/merged/2012/2012-12/
# I get bz file, unzip to get this: 

my_file <- 'pagecounts-2012-12-14/pagecounts-2012-12-14'

# How big is my file?
print(paste(round(file.info(my_file)$size  / 2^30,3), 'gigabytes'))
# [1] "3.493 gigabytes" too big to open in Notepad++ !
# But can read with 010 Editor

# look at the top of the file 
readLines(my_file, n = 100)

# to find where the content starts, vary the skip value, 
read.table(my_file, nrows = 10, skip = 25)

这是我们开始在文件块中工作的地方,我们可以按照通常的方式使用大多数dplyr动词:

代码语言:javascript
复制
# Let the chunked pkg work its magic! We only want the lines containing 
# "Gun_control". The main challenge here was identifying the column
# header
df <- 
read_chunkwise(my_file, 
               chunk_size=5000,
               skip = 30,
               format = "table",
               header = TRUE) %>% 
  filter(stringr::str_detect(De.mw.De.5.J3M1O1, "Gun_control"))

# this line does the evaluation, 
# and takes a few moments...
system.time(out <- collect(df))

这里我们可以像往常一样处理输出,因为它比输入文件小得多:

代码语言:javascript
复制
# clean up the output to separate into cols, 
# and get the number of page views as a numeric
out_df <- 
out %>% 
  separate(De.mw.De.5.J3M1O1, 
           into = str_glue("V{1:4}"),
           sep = " ") %>% 
  mutate(V3 = as.numeric(V3))

 head(out_df)
    V1                                                        V2   V3
1 en.z                                               Gun_control 7961
2 en.z Category:Gun_control_advocacy_groups_in_the_United_States 1396
3 en.z          Gun_control_policy_of_the_Clinton_Administration  223
4 en.z                            Category:Gun_control_advocates   80
5 en.z                         Gun_control_in_the_United_Kingdom   68
6 en.z                                    Gun_control_in_america   59
                                                                                 V4
1 A34B55C32D38E32F32G32H20I22J9K12L10M9N15O34P38Q37R83S197T1207U1643V1523W1528X1319
2                                     B1C5D2E1F3H3J1O1P3Q9R9S23T197U327V245W271X295
3                                     A3B2C4D2E3F3G1J3K1L1O3P2Q2R4S2T24U39V41W43X40
4                                                            D2H1M1S4T8U22V10W18X14
5                                                             B1C1S1T11U12V13W16X13
6                                                         B1H1M1N2P1S1T6U5V17W12X12

#--------------------
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19894194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档