У меня есть массивный набор данных (8 ГБ), который я просто не могу прочитать в R, используя существующую настройку. Попытка использовать fread в наборе данных немедленно приводит к сбою сеанса R, а попытки чтения случайных строк из базового файла было недостаточно, потому что: (1) У меня нет хорошего способа узнать это общее количество строк в наборе данных; (2) мой метод не был настоящей «случайной выборкой».

Эти попытки получить количество строк потерпели неудачу (они занимают столько времени, сколько просто считывают данные в:

  1. length(count.fields("file.dat", sep = "|"))
  2. read.csv.sql("file.dat", header = FALSE, sep = "|", sql = "select count(*) from file")

Есть ли способ с помощью R или какой-либо другой программы сгенерировать случайную выборку из большого базового набора данных?

Возможная идея: возможно ли на основе «выборки» первых нескольких строк получить представление о среднем количестве информации, содержащейся в каждой строке. А затем обратно, сколько строк должно иметь размер набора данных (8 ГБ)? Это не было бы точным, но это могло бы дать фигуру бейсбольного парка, которую я мог бы просто недооценить.

3
Parseltongue 8 Дек 2017 в 19:00

1 ответ

Лучший ответ

Вот один из вариантов, использующий способность fread принимать команду оболочки, которая предварительно обрабатывает файл в качестве входных данных. Используя эту опцию, мы можем запустить скрипт gawk для извлечения необходимых строк. Обратите внимание, что вам может потребоваться установить gawk, если он еще не установлен в вашей системе. Если в вашей системе есть awk, вы можете использовать его.

Сначала создадим фиктивный файл для тестирования:

library(data.table)
dt = data.table(1:1e6, sample(letters, 1e6, replace = TRUE))
write.csv(dt, 'test.csv', row.names = FALSE)

Теперь мы можем использовать команду оболочки wc, чтобы узнать, сколько строк находится в файле:

nl = read.table(pipe("wc -l test.csv"))[[1]]

Возьмите образец номеров строк и запишите их (в порядке возрастания) во временный файл, который сделает их легко доступными для глаз.

N = 20 # number of lines to sample
sample.lines = sort(sample(2:nl, N)) #start sample at line 2 to exclude header 
cat(paste0(sample.lines, collapse = '\n'), file = "lines.txt")

Теперь мы готовы прочитать образец, используя fread и gawk (на основе этого ответа ). Вы также можете попробовать некоторые другие сценарии gawk в этом связанном вопросе, которые могут быть более эффективными для очень больших данных.

dt.sample = fread("gawk 'NR == FNR {nums[$1]; next} FNR in nums' lines.txt test.csv")
3
dww 8 Дек 2017 в 18:17