Чтение 40-гигабайтного CSV файла в R с использованием bigmemory - программирование
Подтвердить что ты не робот

Чтение 40-гигабайтного CSV файла в R с использованием bigmemory

Название здесь довольно понятно, но я расскажу следующее. Некоторые из моих нынешних методов борьбы с этой проблемой основаны на решениях, представленных в этом вопросе. Тем не менее, я столкнулся с несколькими проблемами и ограничениями, поэтому мне было интересно, может ли кто-нибудь попытаться предпринять удар по этой проблеме. Я пытаюсь выяснить проблему, используя bigmemory, но у меня возникли трудности.

Существующие ограничения:

  • Использование Linux-сервера с 16 ГБ оперативной памяти
  • Размер 40 GB CSV
  • Нет строк: 67,194,126,114

Проблемы

  • Необходимо иметь возможность случайным образом отображать меньшие массивы данных (5-10 миллионов строк) из большой или матричной структуры данных.
  • Нужно уметь удалять любую строку с одним экземпляром NULL при разборе в массив big.matrix или эквивалентную структуру данных.

Пока результаты не очень хорошие. Очевидно, что я что-то проваливаю или, может быть, просто недостаточно понимаю документацию bigmemory. Итак, я подумал, что попрошу здесь посмотреть, использовал ли кто-нибудь

Любые советы, советы по этой линии атаки и т.д.? Или я должен перейти на что-то еще? Я прошу прощения, если этот вопрос очень похож на предыдущий, но я думал, что масштабы данных были примерно в 20 раз больше, чем предыдущие. Спасибо!

4b9b3361

Ответ 1

Я не знаю о bigmemory, но чтобы удовлетворить ваши проблемы, вам не нужно читать файл. Просто подключите некоторые bash/awk/sed/python/любую обработку, чтобы выполнить нужные шаги, т.е. выбрасывать строки NULL и произвольно выбирать строки N, а затем читать это.

Вот пример использования awk (если вы хотите, чтобы 100 случайных строк из файла имели 1M строк).

read.csv(pipe('awk -F, \'BEGIN{srand(); m = 100; length = 1000000;}
                       !/NULL/{if (rand() < m/(length - NR + 1)) {
                                 print; m--;
                                 if (m == 0) exit;
                              }}\' filename'
        )) -> df

Для меня не было очевидно, что вы имели в виду под NULL, поэтому я использовал буквальное понимание этого, но его должно легко изменить в соответствии с вашими потребностями.

Ответ 2

Это чисто R-решение проблемы выборки из большого текстового файла; он имеет дополнительную ценность для рисования случайной выборки ровно n. Он не слишком неэффективен, хотя строки анализируются символьными векторами, и это относительно медленно.

Начнем с сигнатуры функции, где мы предоставляем имя файла, размер образца, который мы хотим нарисовать, семя для генератора случайных чисел (чтобы мы могли воспроизвести нашу случайную выборку!), указав, есть строка заголовка, а затем функция "читателя", которую мы будем использовать для синтаксического анализа образца в объект, видимый R, включая дополнительные аргументы ..., которые могут потребоваться для функции чтения

fsample <-
    function(fname, n, seed, header=FALSE, ..., reader=read.csv)
{

Функция засекает генератор случайных чисел, открывает соединение и читает в (необязательной) строке заголовка

    set.seed(seed)
    con <- file(fname, open="r")
    hdr <- if (header) {
        readLines(con, 1L)
    } else character()

Следующий шаг - прочитать в куске n строк, инициализируя счетчик общего количества просмотренных строк

    buf <- readLines(con, n)
    n_tot <- length(buf)

Продолжайте читать в кусках n строк, останавливаясь, когда нет дополнительного ввода

    repeat {
        txt <- readLines(con, n)
        if ((n_txt <- length(txt)) == 0L)
            break

Для каждого фрагмента нарисуйте образец строк n_keep с количеством строк, пропорциональным доле всех строк в текущем фрагменте. Это обеспечивает равномерное выборку строк по файлу. Если строк нет, перейдите к следующему фрагменту.

        n_tot <- n_tot + n_txt
        n_keep <- rbinom(1, n_txt, n_txt / n_tot)
        if (n_keep == 0L)
            next

Выберите строки, которые нужно сохранить, и строки, которые нужно заменить, и обновите буфер

        keep <- sample(n_txt, n_keep)
        drop <- sample(n, n_keep)
        buf[drop] <- txt[keep]
    }

Когда ввод данных выполняется, мы анализируем результат с помощью считывателя и возвращаем результат

    reader(textConnection(c(hdr, buf), header=header, ...)
}

Решение может быть сделано более эффективным, но немного сложнее, используя readBin и поиск разрывов строк, как предложил Саймон Урбанек на R-devel список рассылки. Здесь полное решение

fsample <-
    function(fname, n, seed, header=FALSE, ..., reader = read.csv)
{
    set.seed(seed)
    con <- file(fname, open="r")
    hdr <- if (header) {
        readLines(con, 1L)
    } else character()

    buf <- readLines(con, n)
    n_tot <- length(buf)

    repeat {
        txt <- readLines(con, n)
        if ((n_txt <- length(txt)) == 0L)
            break

        n_tot <- n_tot + n_txt
        n_keep <- rbinom(1, n_txt, n_txt / n_tot)
        if (n_keep == 0L)
            next

        keep <- sample(n_txt, n_keep)
        drop <- sample(n, n_keep)
        buf[drop] <- txt[keep]
    }

    reader(textConnection(c(hdr, buf)), header=header, ...)
}