Хобрук: Ваш путь к мастерству в программировании

Выборка 10 000 случайных строк из набора данных объемом 200 ГБ

Я пытаюсь выбрать 10000 случайных строк из большого набора данных с ~ 3 миллиардами строк (с заголовками). Я рассматривал возможность использования shuf -n 1000 input.file > output.file, но это кажется довольно медленным (> 2 часа работы с моими текущими доступными ресурсами).

Я также использовал awk 'BEGIN{srand();} {a[NR]=$0} END{for(i=1; i<=10; i++){x=int(rand()*NR) + 1; print a[x];}}' input.file > output.file из этого ответа для процента строк из небольших файлов, хотя я новичок в awk и не не знаю, как включить заголовки.

Я хотел знать, есть ли более эффективное решение для выборки подмножества (например, 10000 строк) данных из набора данных объемом 200 ГБ.

02.07.2020

  • shuf будет самым быстрым. 02.07.2020
  • есть несколько способов сделать это в R на кадре данных, но я не знаю, будет ли это быстрее 02.07.2020
  • Если вы согласны со стратифицированной выборкой, вы можете разделить большой файл данных, скажем, на 1000 разделов по 3 м записей в каждом, взять 10 образцов из каждого и объединить образцы обратно. 02.07.2020

Ответы:


1

Я не думаю, что какая-либо программа, написанная на языке сценариев, может превзойти shuf в контексте этого вопроса. Во всяком случае, это моя попытка в bash. Запустите его с помощью ./scriptname input.file > output.file

#!/bin/bash

samplecount=10000
datafile=$1
[[ -f $datafile && -r $datafile ]] || {
    echo "Data file does not exists or is not readable" >&2
    exit 1
}

linecount=$(wc -l "$datafile")
linecount=${linecount%% *}
pickedlinnum=(-1)
mapfile -t -O1 pickedlinnum < <(
    for ((i = 0; i < samplecount;)); do
        rand60=$((RANDOM + 32768*(RANDOM + 32768*(RANDOM + 32768*RANDOM))))
        linenum=$((rand60 % linecount))
        if [[ -z ${slot[linenum]} ]]; then # no collision
            slot[linenum]=1
            echo ${linenum}
            ((++i))
        fi
    done | sort -n)

for ((i = 1; i <= samplecount; ++i)); do
    mapfile -n1 -s$((pickedlinnum[i] - pickedlinnum[i-1] - 1))
    echo -n "${MAPFILE[0]}"
done < "$datafile"
03.07.2020

2

Что-то в авк. Предоставьте ему случайное начальное число ($RANDOM в Bash) и количество требуемых записей n. Он подсчитывает строки с wc -l и использует это количество для случайного выбора n значений между 1—lines[1] в file и выводит их. По скорости ничего не могу сказать, у меня даже 200 Гб диска нет. (:

$ awk -v seed=$RANDOM -v n=10000 '
BEGIN {
    cmd="wc -l " ARGV[1]                          # use wc  for line counting
    if(ARGV[1]==""||n==""||(cmd | getline t)<=0)  # require all parameters
        exit 1                                    # else exit
    split(t,lines)                                # wc -l returns "lines filename"
    srand(seed)                                   # use the seed
    while(c<n) {                                  # keep looping n times
        v=int((lines[1]) * rand())+1              # get a random line number
        if(!(v in a)){                            # if its not used yet
            a[v]                                  # use it
            ++c                                   
        }
    }
}
(NR in a)' file                                   # print if NR in selected

Тестирование с набором данных от seq 1 100000000. shuf -n 10000 file заняло около 6 секунд, тогда как приведенный выше awk занял около 18 секунд.

02.07.2020
  • Это работало довольно хорошо с небольшими файлами, и стоит попробовать запустить это с большим файлом, чтобы хотя бы сравнить со временем выполнения shuf. Постараюсь через пару дней отчитаться. 02.07.2020
  • Проверено с помощью awk, и это заняло ~ 2 часа с awk, а не ~ 1,7 часа с shuf. 07.07.2020
  • @Geode На удивление не так уж и плохо. Спасибо за регистрацию. 07.07.2020
  • Новые материалы

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..

    Обзор 20 основных и современных методов работы с массивами в JavaScript
    Вы знаете их всех? В этом коротком посте я покажу сводку методов, доступных в JavaScript для работы с массивами. Я надеюсь, что вы найдете это полезным! В конце поста вы найдете ссылку на..

    Да, но я чувствую необходимость указать, что это или не единственные два.
    Да, но я чувствую необходимость указать, что это или не единственные два. Обучение с подкреплением (в качестве примера) также является важным.