2013-07-03 8 views
51

현재 최대 1 백만 행 및 200 열 (파일 범위는 100MB - 1.6GB)의 Python 2.7에서 .csv 파일의 데이터를 읽으려고합니다. 나는 300,000 행 이하의 파일들에 대해서 (매우 천천히)이 작업을 수행 할 수 있지만, 일단 나는 메모리 오류를 얻는다. 내 코드는 다음과 같습니다거대한 .csv 파일 읽기

def getdata(filename, criteria): 
    data=[] 
    for criterion in criteria: 
     data.append(getstuff(filename, criteron)) 
    return data 

def getstuff(filename, criterion): 
    import csv 
    data=[] 
    with open(filename, "rb") as csvfile: 
     datareader=csv.reader(csvfile) 
     for row in datareader: 
      if row[3]=="column header": 
       data.append(row) 
      elif len(data)<2 and row[3]!=criterion: 
       pass 
      elif row[3]==criterion: 
       data.append(row) 
      else: 
       return data 

getstuff 함수의 다른 절에 대한 이유는 내가 과거를 얻을 때 기준이 CSV 파일에 함께 표시됩니다 맞는, 그래서 모든 요소가 나는 루프를두고 있다는 것입니다 시간을 절약 할 수 있습니다.

내 질문은 :

  1. 가 어떻게이 큰 파일 작업을 얻을 관리 할 수 ​​있습니까?

  2. 내가 더 빨리 만들 수있는 방법이 있습니까?

내 컴퓨터가 윈도우 7 64 비트를 실행, 8 기가 바이트 RAM을 가지고 있으며, 프로세서 3.40 GHz의 (당신이 필요로하는 정보가 무엇인지 확실하지)입니다.

도움을 주셔서 감사합니다.

+1

내가 몇 가지 비슷한 보이는 문제가 있다는 것을 알고 있어요,하지만 그들 중 누구도 많은 도움이 내 문제에 충분한 구체적 것 같았다. 내가 놓친 것이 있으면 미안해. –

+0

읽은 데이터를 메모리에 저장하는 대신 데이터베이스 (예 : Sqlite)에 저장해야합니다. 그런 다음 데이터베이스에서 필터링과 같은 추가 처리를 수행 할 수 있습니다. –

답변

101

모든 행을 목록으로 읽은 다음 해당 목록을 처리하고 있습니다. 하지 마십시오.

생산할 때 행을 처리하십시오. 먼저 데이터를 필터링해야하는 경우, 발전기 기능 사용 : 나는 또한 필터 테스트를 단순화

import csv 

def getstuff(filename, criterion): 
    with open(filename, "rb") as csvfile: 
     datareader = csv.reader(csvfile) 
     count = 0 
     for row in datareader: 
      if row[3] in ("column header", criterion): 
       yield row 
       count += 1 
      elif count < 2: 
       continue 
      else: 
       return 
을; 논리는 동일하지만보다 간결합니다.

이제 getstuff()을 직접 반복 할 수 있습니다. getdata()에서 동일한 작업을 수행 : getdata()를 통해 직접

def getdata(filename, criteria): 
    for criterion in criteria: 
     for row in getstuff(filename, criterion): 
      yield row 

이제 루프를 코드에서 : 당신은 이제 메모리에 한 행를 개최

for row in getdata(somefilename, sequence_of_criteria): 
    # process row 

, 대신 기준 당 라인의 당신의 수천.

yield은 기능을 generator function으로 만듭니다. 즉, 반복 할 때까지 아무 작업도 수행하지 않습니다.

+0

답변 해 주셔서 감사합니다! 당신이 "생산할 때 행을 처리"한다는 것이 무슨 뜻인지 잘 모르겠습니다. 나는 내가 다양한 방식으로 읽고있는 데이터를 필요로하는 약 15 개의 다른 함수를 가지고 있기 때문에 변수의 모든 행을 필요로한다고 생각한다. 또한 정확히 "양보"하는 것은 여기서 무엇을합니까? –

+0

죄송합니다. 이러한 질문이 멍청한 질문이라면, 저는 1 주일 정도만 Python을 사용했습니다. –

+0

@ user2545862 : 둘을 결합 할 수 없습니다. 하나씩 행을 처리하고 나머지 기능을 조정하여 메모리에서 모든 것을 읽고 데이터 세트를 반복적으로 반복합니다. 그리고 그것은 모든 것을 잡을 수있는 충분한 기억을 필요로합니다. –

-1

pytables를 사용하십시오. "PyTables는 계층 적 데이터 세트를 관리하기위한 패키지이며 대용량 데이터에 효율적이고 쉽게 대처할 수 있도록 설계되었습니다."

1

저는 최근에 같은 문제를 해결하려고했지만 python pandas 패키지가 상당히 효율적이라는 것을 알았습니다.

당신은 여기에서 확인 할 수 있습니다, http://pandas.pydata.org/

팬더는 빅 데이터에 대한 고성능 데이터 분석 라이브러리입니다.

+1

편리한 사용을 위해이 게시물을 확인하십시오. http://stackoverflow.com/questions/23853553/python-pandas-how-to-read-only-first-n-rows-of-csv-files-in –

+3

팬더 시작 너머의 파일들, 예를 들어 50-70Mb로 고생하고 있습니다. 100MB 파일 (메모리에 행을 탐독하여 작업 정리, 계산 등)을 할 경우, 몇 분 동안 만 정리하면 2.30 분이 걸립니다. 이 대기 시간이 좋으면 팬더가 아름답고 매우 편리합니다. 나는 곧 이걸 시험해 볼거야. 그러나 유망 해 보인다. - http://stackoverflow.com/questions/14262433/large-data-work-flows-using-pandas. 가능하다면, 팬더에서 섭취하기 전에 그것을 알아 채십시오. – shingav

5

상당한 진동 분석을하고 많은 데이터 세트 (수천 억 포인트)를 살펴 봅니다.내 테스트는 pandas.read_csv() 기능이 번 numpy.genfromtxt()보다 빠르다는 것을 보여주었습니다. 그리고 genfromtxt() 함수는 numpy.loadtxt()보다 3 배 빠릅니다. 그것은 당신이 큰 데이터 세트에 대한 팬더가 필요해 보인다.

나는이 테스트에서 사용한 코드와 데이터 세트를 블로그 (MATLAB vs Python for vibration analysis)에 게시했습니다.

8

Martijin의 대답은 prob best입니다. 초보자를위한 대형 csv 파일을 처리하는보다 직관적 인 방법이 있습니다. 이렇게하면 한 번에 행 그룹 또는 청크를 처리 할 수 ​​있습니다.

import pandas as pd 
chunksize = 10 ** 8 
for chunk in pd.read_csv(filename, chunksize=chunksize): 
    process(chunk) 
+1

팬더를 사용하면 왜 더 직관적입니까? – wwii

+2

코드 네 줄은 항상 나 같은 새내기에 더 좋습니다. – mmann1123

+0

일반 파이썬 코드는 짧은 코드이므로 한 줄에 처리 할 수 ​​있습니다.생성자 함수는 필터 항목에만 있습니다. 판다 스에서 같은 필터링을 어떻게하면 될까요? –

-1

생성기는 좋은 해결책입니다. 사실, 코드를 추가하기 전에 (사실 csv를 열기 전에) 무한히 많은 루프를 반복 할 수 있습니다. mnist 데이터 세트에 대한 예를 들어

:

import gzip 
import numpy as np 
BATCHSIZE = 100 
DATASIZE = 1000 
LOOP = DATASIZE//BATCHSIZE 
def mnist_generator_iterable(path, name='train_data'): 
if name=='train_data': 
    while True: 
     with gzip.open(path+'\\train-images-idx3-ubyte.gz') as bytestream: 
      bytestream.read(16) 
      for i in range(LOOP): 
       buf = bytestream.read(28*28*BATCHSIZE*1) 
       trainset = np.frombuffer(buf, dtype=np.uint8).astype(np.float32) 
       yield trainset.reshape([-1,784])