Вопрос по r, data.table, fread – Чтение по частям с использованием fread в пакете data.table

25

я пытаюсь ввести большой файл с разделителями табуляции (около 2 ГБ), используяfread функция в пакетеdata.table, Однако, потому что этотакой большой, это неТ полностью вписывается в память. Я попытался ввести его кусками, используяskip а такжеnrow такие аргументы как:

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)
@Arun Есть ли FR на новой странице GitHub? Я могу'кажется, не нашел его Zach
Там'похожий FRВот, Я'Я также буду ссылаться на этот пост. Arun
это возможно сейчас? EDC
Была такая же проблема сегодня user3375672

Ваш Ответ

3   ответа
11

LaF пакет. Это вводит своего рода указатель на ваши данные, таким образом избегая - для очень больших данных - раздражающего поведения чтения всего файла. Насколько я понимаюfread() вdata.table pckg нужно знать общее количество строк, которое занимает время для данных в ГБ. Используя указатель вLaF Вы можете перейти к любой строке (строкам), которую хотите; и читайте порции данных, к которым вы можете применить свою функцию, а затем переходите к следующей порции данных. На моем маленьком ПК я запускал csv-файл объемом 25 ГБ с шагом 10e6 строк и извлекал все необходимые ~ 5e6 наблюдений - каждый фрагмент 10e6 занимал 30 секунд.

ОБНОВИТЬ:

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)

Затем создайте соединение с вашим файлом, используя модель:

df.laf <- laf_open(model)

После этого вы можете делать все что угодно, не зная размер файла, как в data.table pckgs. Например, поместите указатель на строку № 100e6 и прочитайте 1e6 строк данных отсюда:

goto(df.laf, 100e6)
data <- next_block(df.laf,nrows=1e6)

Сейчасdata содержит 1e6 строк вашего CSV-файла (начиная со строки 100e6).

Вы можете читать порциями данные (размер зависит от вашей памяти) и хранить только то, что вам нужно. напримерhuge_file в моем примере указывает на файл со всеми известными белковыми последовательностями и имеет размер>27 ГБ - путь к большому для моего ПК. Чтобы получить только человеческую последовательность, я отфильтровал, используя идентификатор организма, который для человека равен 9606, и это должно появиться в начале переменнойprotein1, Грязный способ - поместить его в простой цикл for и просто читать один блок данных за раз:

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() принимает в качестве аргумента функцию. Следовательно, в функции вы делаете то, что вы хотите для каждого фрагмента данных. Прочитайте документацию.

Можете ли вы привести пример кода? FBC
Да, пожалуйста, посмотрите ОБНОВЛЕНИЕ. user3375672
7

Вы можете использовать readrread_*_chunked читать данные и, например, отфильтруйте его по кусочкам. УвидетьВот а такжеВот для примера:

# 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)
4

Связанная опция - этофрагментированный пакет. Вот пример с 3,5 ГБ текстовым файлом:

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 обычным способом:

# 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))

И здесь мы можем работать с выводом как обычно, так какнамного меньше, чем входной файл:

# 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

#--------------------
Да, хотя более удобный ИМО Ben
Кажетсяchunked Это'Обертка вокруг.LaF Artem Klevtsov

Похожие вопросы