Чтение строк по номеру из большого файла - PullRequest
24 голосов
/ 23 августа 2011

У меня есть файл с 15 миллионами строк (не помещается в памяти).У меня также есть небольшой вектор номеров строк - строк, которые я хочу извлечь.

Как я могу считывать строки за один проход?

Я надеялся на функцию C, котораяделает это за один проход.

Ответы [ 5 ]

25 голосов
/ 23 августа 2011

Хитрость заключается в том, чтобы использовать соединение И открыть его до read.table:

con<-file('filename')
open(con)

read.table(con,skip=5,nrow=1) #6-th line
read.table(con,skip=20,nrow=1) #27-th line
...
close(con)

Вы также можете попробовать scan, это быстрее и дает больше контроля.

5 голосов
/ 23 августа 2011

Если это двоичный файл

Здесь обсуждается: Чтение только части файла Stata .DTA в R

Если это CSV или другой текстfile

Если они являются смежными и находятся вверху файла, просто используйте аргумент ,nrows для read.csv или любого из read.table семейства.Если нет, вы можете объединить аргументы ,nrows и ,skip для многократного вызова read.csv (считывание новой строки или группы смежных строк при каждом вызове), а затем rbind результаты вместе.

4 голосов
/ 23 августа 2011

Если ваш файл имеет фиксированную длину строки, вы можете использовать 'seek', чтобы перейти к любой позиции символа.Поэтому просто перейдите к N * line_length для каждого нужного вам N и прочитайте одну строку.

Однако, из R документов:

 Use of seek on Windows is discouraged.  We have found so many
 errors in the Windows implementation of file positioning that
 users are advised to use it only at their own risk, and asked not
 to waste the R developers' time with bug reports on Windows'
 deficiencies.

Вы также можете использовать 'seek' из стандартногоБиблиотека C на C, но я не знаю, применимо ли приведенное выше предупреждение!

3 голосов
/ 23 августа 2011

Прежде чем я смог получить решение / ответ R, я сделал это в Ruby:

#!/usr/bin/env ruby

NUM_SEQS = 14024829

linenumbers = (1..10).collect{(rand * NUM_SEQS).to_i}

File.open("./data/uniprot_2011_02.tab") do |f|
  while line = f.gets
    print line if linenumbers.include? f.lineno 
  end
end

работает быстро (так быстро, как мое хранилище может читать файл).

2 голосов
/ 09 октября 2016

Я собираю решение на основе обсуждений здесь .

scan(filename,what=list(NULL),sep='\n',blank.lines.skip = F)

Это покажет вам только количество строк, но ничего не прочитает. Если вы действительно хотите пропустить пустые строки, вы можете просто установить последний аргумент в TRUE.

...