파일의 하위 집합을 무작위로 샘플링하는 방법

파일의 하위 집합을 무작위로 샘플링하는 방법

파일의 하위 집합을 샘플링하는 데 사용할 수 있는 Linux 명령이 있습니까? 예를 들어 파일에 백만 개의 줄이 포함되어 있고 파일에서 천 개의 줄만 무작위로 샘플링하려고 합니다.

무작위라는 것은 모든 라인이 선택될 확률이 동일하고 선택된 라인 중 어느 것도 중복되지 않는다는 것을 의미합니다.

headtail파일의 하위 집합을 선택할 수 있지만 무작위로 선택할 수는 없습니다 . 이 작업을 수행하기 위해 언제든지 Python 스크립트를 작성할 수 있다는 것을 알고 있지만 이에 대한 명령이 있는지 궁금합니다.

답변1

명령 shuf(coreutils의 일부)으로 다음을 수행할 수 있습니다.

shuf -n 1000 file

적어도 지금은 비고대 버전(추가됨)2013년부터의 약속), 이는 적절한 경우 저장소 샘플링을 사용합니다. 즉, 메모리가 부족하지 않아야 하며 빠른 알고리즘을 사용하고 있음을 의미합니다.

답변2

당신이 가지고 있다면매우 크다파일(샘플링의 일반적인 이유임)에서 다음을 찾을 수 있습니다.

  1. shuf메모리 부족
  2. $RANDOM파일이 32767줄을 초과하면 정상적으로 사용할 수 없습니다.

"정확히" n개의 샘플 라인이 필요하지 않은 경우당신은 할 수샘플링 비율이와 같이:

cat input.txt | awk 'BEGIN {srand()} !/^$/ { if (rand() <= .01) print $0}' > sample.txt

이것사용영구 메모리, 파일의 1%를 샘플링합니다(파일의 줄 수를 알고 있는 경우 이 요소를 조정하여 거의 제한된 수의 줄을 샘플링할 수 있음).어떤 크기에도 적합하지만 그 파일~하지 않을 것이다반환정밀한행 수는 단지 통계적 비율일 뿐입니다.

참고: 코드 출처:https://stackoverflow.com/questions/692312/randomly-pick-lines-from-a-file-without-slurping-it-with-unix

답변3

@Txangel의 확률 솔루션과 유사하지만 100배 더 빠릅니다.

perl -ne 'print if (rand() < .01)' huge_file.csv > sample.csv

고성능, 정확한 샘플 크기가 필요하고 파일 끝에 샘플 간격을 허용하려는 경우 다음과 같이 수행할 수 있습니다(1m 라인 파일에서 1000라인 샘플링).

perl -ne 'print if (rand() < .0012)' huge_file.csv | head -1000 > sample.csv

..또는 실제로 두 번째 예제 방법을 대신 연결하십시오 head.

답변4

헤더 행을 보존하고 샘플이 파일의 대략적인 비율이 될 수 있을 때 awk를 사용하는 것을 좋아합니다. 매우 큰 파일의 경우:

awk 'BEGIN {srand()} !/^$/ { if (rand() <= .01 || FNR==1) print > "data-sample.txt"}' data.txt

관련 정보