[Python] 큰 CSV 파일에서 작은 무작위 표본을 파이썬 데이터 프레임으로 읽습니다.


Answers

CSV 파일에 헤더가 없다고 가정합니다.

import pandas
import random

n = 1000000 #number of records in file
s = 10000 #desired sample size
filename = "data.txt"
skip = sorted(random.sample(xrange(n),n-s))
df = pandas.read_csv(filename, skiprows=skip)

read_csv에 keeprows가 있거나 skiprows가 목록 대신 콜백 함수를 사용하면 더 좋을 것입니다.

머리글 및 알 수없는 파일 길이 포함 :

import pandas
import random

filename = "data.txt"
n = sum(1 for line in open(filename)) - 1 #number of records in file (excludes header)
s = 10000 #desired sample size
skip = sorted(random.sample(xrange(1,n+1),n-s)) #the 0-indexed header will not be included in the skip list
df = pandas.read_csv(filename, skiprows=skip)
Question

읽으려는 CSV 파일이 주 메모리에 맞지 않습니다. 몇 개의 (~ 10K) 무작위 라인을 읽고 선택한 데이터 프레임에 대한 간단한 통계를 작성하려면 어떻게해야합니까?




이것은 팬더가 아니지만 bash를 통해 훨씬 빨리 동일한 결과를 얻을 수 있습니다.

shuf -n 100000 data/original.tsv > data/sample.tsv

shuf 명령은 입력을 셔플하고 -n 인수는 출력에서 ​​원하는 행 수를 나타냅니다.

관련 질문 : https://unix.stackexchange.com/q/108581




아니 팬더!

import random
from os import fstat
from sys import exit

f = open('/usr/share/dict/words')

# Number of lines to be read
lines_to_read = 100

# Minimum and maximum bytes that will be randomly skipped
min_bytes_to_skip = 10000
max_bytes_to_skip = 1000000

def is_EOF():
    return f.tell() >= fstat(f.fileno()).st_size

# To accumulate the read lines
sampled_lines = []

for n in xrange(lines_to_read):
    bytes_to_skip = random.randint(min_bytes_to_skip, max_bytes_to_skip)
    f.seek(bytes_to_skip, 1)
    # After skipping "bytes_to_skip" bytes, we can stop in the middle of a line
    # Skip current entire line
    f.readline()
    if not is_EOF():
        sampled_lines.append(f.readline())
    else:
        # Go to the begginig of the file ...
        f.seek(0, 0)
        # ... and skip lines again
        f.seek(bytes_to_skip, 1)
        # If it has reached the EOF again
        if is_EOF():
            print "You have skipped more lines than your file has"
            print "Reduce the values of:"
            print "   min_bytes_to_skip"
            print "   max_bytes_to_skip"
            exit(1)
        else:
            f.readline()
            sampled_lines.append(f.readline())

print sampled_lines

sampled_lines 목록으로 끝납니다. 어떤 종류의 통계입니까?




class magic_checker:
    def __init__(self,target_count):
        self.target = target_count
        self.count = 0
    def __eq__(self,x):
        self.count += 1
        return self.count >= self.target

min_target=100000
max_target = min_target*2
nlines = randint(100,1000)
seek_target = randint(min_target,max_target)
with open("big.csv") as f:
     f.seek(seek_target)
     f.readline() #discard this line
     rand_lines = list(iter(lambda:f.readline(),magic_checker(nlines)))

#do something to process the lines you got returned .. perhaps just a split
print rand_lines
print rand_lines[0].split(",")

그런 식으로 생각해야 할 것 같아.




다음은 파일의 행 수를 미리 계산하지 않아도되기 때문에 파일을 한 번만 읽으면됩니다.

m 개의 샘플을 원한다고합시다. 첫째, 알고리즘은 첫 번째 m 샘플을 유지합니다. 확률 m / i로 i 번째 샘플 (i> m)을 볼 때 알고리즘은 샘플을 사용하여 이미 선택된 샘플을 무작위로 바꿉니다.

이렇게함으로써, 어떤 i> m에 대해서도, 우리는 항상 첫 번째 샘플로부터 무작위로 선택된 m 개의 샘플의 부분 집합을 가진다.

아래 코드를 참조하십시오.

import random

n_samples = 10
samples = []

for i, line in enumerate(f):
    if i < n_samples:
        samples.append(line)
    elif random.random() < n_samples * 1. / (i+1):
            samples[random.randint(0, n_samples-1)] = line



다음 코드는 먼저 헤더를 읽은 다음 다른 행에서 무작위 샘플을 읽습니다.

import pandas as pd
import numpy as np

filename = 'hugedatafile.csv'
nlinesfile = 10000000
nlinesrandomsample = 10000
lines2skip = np.random.choice(np.arange(1,nlinesfile+1), (nlinesfile-nlinesrandomsample), replace=False)
df = pd.read_csv(filename, skiprows=lines2skip)