Reading a huge .csv file
我目前正在尝试从python 2.7中的.csv文件中读取数据,最多100万行,200列(文件大小从100MB到1.6GB)。对于30万行以下的文件,我可以这样做(非常慢),但一旦我超过了这一点,就会出现内存错误。我的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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文件中,所以当我超过这些元素时,就离开循环以节省时间。
我的问题是:
我如何才能让它与更大的文件一起工作?
有什么方法可以让我更快吗?
我的电脑有8GB内存,运行64位Windows7,处理器是3.40GHz(不确定你需要什么信息)。
非常感谢您的帮助!
您正在将所有行读取到一个列表中,然后处理该列表。不要那样做。
在生成行时处理它们。如果需要先筛选数据,请使用生成器函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
我还简化了您的过滤器测试;逻辑是相同的,但更简洁。
因为您只匹配与条件匹配的单个行序列,所以也可以使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 |
现在可以直接循环访问
1 2 3 4 | def getdata(filename, criteria): for criterion in criteria: for row in getstuff(filename, criterion): yield row |
现在在代码中直接循环
1 2 | for row in getdata(somefilename, sequence_of_criteria): # process row |
现在,您在内存中只保存一行,而不是按照标准保存数千行。
尽管马提金的回答是最好的。这是一种更直观的方法来处理初学者的大型csv文件。这允许您一次处理一组行或块。
1 2 3 4 | 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振动分析的博客上发布了测试中使用的代码和数据集。
对我有用的东西过去和现在都是超快的
1 2 3 4 5 6 7 | 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) |
另一个有效的解决方案是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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的方法:
1 2 3 4 5 6 7 8 9 10 | 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 |
这里,