대용량 .csv 파일 읽기
현재 Python 2.7의 .csv 파일에서 최대 100만 개의 행과 200개의 열(파일 범위는 100mb에서 1.6gb)의 데이터를 읽으려고 합니다.행 수가 300,000개 미만인 파일에 대해 이 작업을 매우 느리게 수행할 수 있지만, 이 작업을 수행하면 메모리 오류가 발생합니다.내 코드는 다음과 같습니다.
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 함수에 else 절이 있는 이유는 csv 파일에 기준에 맞는 모든 요소가 함께 나열되기 때문에 시간을 절약하기 위해 통과할 때 루프를 탈퇴합니다.
제 질문은 다음과 같습니다.
어떻게 하면 더 큰 파일에서 이 작업을 수행할 수 있을까요?
제가 더 빨리 할 수 있는 방법이 있나요?
내 컴퓨터에는 64비트 Windows 7(윈도우 7)을 실행하는 8GB RAM이 있고 프로세서는 3.40GHz(필요한 정보가 확실하지 않음)입니다.
모든 행을 목록으로 읽은 다음 해당 목록을 처리하는 중입니다.그러지 마세요.
행을 생성할 때 행을 처리합니다.데이터를 먼저 필터링해야 하는 경우 제너레이터 기능을 사용합니다.
import csv
def getstuff(filename, criterion):
with open(filename, "rb") as csvfile:
datareader = csv.reader(csvfile)
yield next(datareader) # yield the header row
count = 0
for row in datareader:
if row[3] == criterion:
yield row
count += 1
elif count:
# done when having read a consecutive series of rows
return
저는 또한 당신의 필터 테스트를 단순화했습니다. 논리는 동일하지만 더 간결합니다.
조건과 일치하는 행의 단일 시퀀스만 일치하므로 다음을 사용할 수도 있습니다.
import csv
from itertools import dropwhile, takewhile
def getstuff(filename, criterion):
with open(filename, "rb") as csvfile:
datareader = csv.reader(csvfile)
yield next(datareader) # yield the header row
# first row, plus any subsequent rows that match, then stop
# reading altogether
# Python 2: use `for row in takewhile(...): yield row` instead
# instead of `yield from takewhile(...)`.
yield from takewhile(
lambda r: r[3] == criterion,
dropwhile(lambda r: r[3] != criterion, datareader))
return
이제 루프오버할 수 있습니다.getstuff()
직접적으로.에서 동일한 작업 수행getdata()
:
def getdata(filename, criteria):
for criterion in criteria:
for row in getstuff(filename, criterion):
yield row
이제 직접 루프합니다.getdata()
코드:
for row in getdata(somefilename, sequence_of_criteria):
# process row
이제 기준당 수천 개의 행 대신 메모리에 하나의 행만 저장할 수 있습니다.
yield
함수를 생성기 함수로 만듭니다. 즉, 루프를 시작할 때까지 아무런 작업도 수행하지 않습니다.
마르티진의 대답이 아마도 가장 좋을 것입니다.초보자를 위해 대용량 CSV 파일을 보다 직관적으로 처리할 수 있는 방법이 있습니다.이렇게 하면 행 그룹 또는 청크를 한 번에 처리할 수 있습니다.
import pandas as pd
chunksize = 10 ** 8
for chunk in pd.read_csv(filename, chunksize=chunksize):
process(chunk)
저는 상당한 양의 진동 분석을 수행하고 대용량 데이터 세트(수천만 개, 수억 개의 포인트)를 살펴봅니다.테스트 결과 panda.read_csv() 기능이 tatts()의 numpy.gen보다 20배 더 빠릅니다.그리고 genfrom tex() 기능은 numpy.load tex()보다 3배 빠릅니다.대용량 데이터 세트를 위해서는 팬더가 필요한 것 같습니다.
저는 이번 테스트에서 사용한 코드와 데이터 세트를 MATLAB 대 Python의 진동 분석에 대해 논의하는 블로그에 게시했습니다.
이 질문에 도달한 사람을 위해.'chunksize'와 'usecols'가 있는 판다를 사용하는 것은 다른 제안된 옵션보다 큰 zip 파일을 더 빨리 읽는 데 도움이 되었습니다.
import pandas as pd
sample_cols_to_keep =['col_1', 'col_2', 'col_3', 'col_4','col_5']
# First setup dataframe iterator, ‘usecols’ parameter filters the columns, and 'chunksize' sets the number of rows per chunk in the csv. (you can change these parameters as you wish)
df_iter = pd.read_csv('../data/huge_csv_file.csv.gz', compression='gzip', chunksize=20000, usecols=sample_cols_to_keep)
# this list will store the filtered dataframes for later concatenation
df_lst = []
# Iterate over the file based on the criteria and append to the list
for df_ in df_iter:
tmp_df = (df_.rename(columns={col: col.lower() for col in df_.columns}) # filter eg. rows where 'col_1' value grater than one
.pipe(lambda x: x[x.col_1 > 0] ))
df_lst += [tmp_df.copy()]
# And finally combine filtered df_lst into the final lareger output say 'df_final' dataframe
df_final = pd.concat(df_lst)
나에게 효과가 있었던 것과 매우 빠른 것은
import pandas as pd
import dask.dataframe as dd
import time
t=time.clock()
df_train = dd.read_csv('../data/train.csv', usecols=[col1, col2])
df_train=df_train.compute()
print("load train: " , time.clock()-t)
또 다른 작동 솔루션은 다음과 같습니다.
import pandas as pd
from tqdm import tqdm
PATH = '../data/train.csv'
chunksize = 500000
traintypes = {
'col1':'category',
'col2':'str'}
cols = list(traintypes.keys())
df_list = [] # list to hold the batch dataframe
for df_chunk in tqdm(pd.read_csv(PATH, usecols=cols, dtype=traintypes, chunksize=chunksize)):
# Can process each chunk of dataframe here
# clean_data(), feature_engineer(),fit()
# Alternatively, append the chunk to list and merge all
df_list.append(df_chunk)
# Merge all dataframes into one dataframe
X = pd.concat(df_list)
# Delete the dataframe list to release memory
del df_list
del df_chunk
다음은 Python3를 위한 다른 솔루션입니다.
import csv
with open(filename, "r") as csvfile:
datareader = csv.reader(csvfile)
count = 0
for row in datareader:
if row[3] in ("column header", criterion):
doSomething(row)
count += 1
elif count > 2:
break
여기서datareader
는 제너레이터 함수입니다.
만약 당신이 팬더를 사용하고 있고 RAM이 많다면 (전체 파일을 메모리에 읽기에 충분합니다)low_memory=False
항목:
import pandas as pd
data = pd.read_csv('file.csv', low_memory=False)
언급URL : https://stackoverflow.com/questions/17444679/reading-a-huge-csv-file
'bestsource' 카테고리의 다른 글
Oracle에서 선언/시작/종료 블록에서 행을 반환하는 방법은 무엇입니까? (0) | 2023.07.18 |
---|---|
전체 디렉터리 트리에 대한 줄 끝 부분 변환(Git) (0) | 2023.07.18 |
패키지 하위 디렉터리의 데이터 액세스 (0) | 2023.07.18 |
마지막 Git 커밋을 준비되지 않은 영역으로 이동(또는 "실행 취소") (0) | 2023.07.18 |
셸 명령을 직접 실행하는 대신 파이썬의 OS 모듈 방식을 사용하는 이유는 무엇입니까? (0) | 2023.07.18 |