현재 Python 2.7의 .csv 파일에서 최대 1 백만 개의 행과 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을 실행하는 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
함수를 생성기 함수로 만듭니다. 즉, 루프를 시작할 때까지 작업을 수행하지 않습니다.
답변
Martijin의 대답이 가장 좋습니다. 초보자를 위해 대용량 csv 파일을보다 직관적으로 처리하는 방법이 있습니다. 이를 통해 한 번에 행 그룹 또는 청크를 처리 할 수 있습니다.
import pandas as pd
chunksize = 10 ** 8
for chunk in pd.read_csv(filename, chunksize=chunksize):
process(chunk)
답변
저는 상당한 양의 진동 분석을 수행하고 대규모 데이터 세트 (수천 및 수억 포인트)를 봅니다. 내 테스트에 따르면 pandas.read_csv () 함수 는 numpy.genfromtxt () 보다 20 배 빠릅니다. 그리고 genfromtxt () 함수는 numpy.loadtxt ()보다 3 배 빠릅니다. 큰 데이터 세트에는 팬더 가 필요한 것 같습니다 .
이 테스트에서 사용한 코드와 데이터 세트 를 진동 분석을위한 MATLAB과 Python을 논의하는 블로그에 게시했습니다 .
답변
나를 위해 일했고 초고속은
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
답변
이 질문에 착수하는 사람을 위해. ‘ chunksize ‘및 ‘ usecols ‘와 함께 pandas 를 사용 하면 다른 제안 된 옵션보다 큰 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)
답변
다음은 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
생성기 함수가 있습니다.
답변
pandas를 사용하고 있고 RAM이 많은 경우 (전체 파일을 메모리로 읽을 수있을만큼) pd.read_csv
with를 사용해보십시오 low_memory=False
. 예 :
import pandas as pd
data = pd.read_csv('file.csv', low_memory=False)
