我对Python和Pandas都很陌生,并且试图找出在大约1,100万行的左数据集和具有~160K行和4的右数据集之间执行庞大的左外连接的最快方法列。这应该是多对一的情况,但如果右侧有重复的行,我希望联接不会出错。我在具有8 Gb RAM的Windows 7 64位系统上使用Canopy Express,我几乎坚持这一点。
这是我到目前为止所编写代码的模型:
import pandas as pd
leftcols = ['a','b','c','d','e','key']
leftdata = pd.read_csv("LEFT.csv", names=leftcols)
rightcols = ['x','y','z','key']
rightdata = pd.read_csv("RIGHT.csv", names=rightcols)
mergedata = pd.merge(leftdata, rightdata, on='key', how='left')
mergedata.to_csv("FINAL.csv")
这适用于小文件但在我的系统上产生MemoryError,文件大小比我实际需要合并的文件大小小两个数量级。
我一直在浏览相关问题(one,two,three),但没有一个答案真正解决了这个基本问题 - 或者如果他们这样做,那么&# #39;没有得到足够的解释,我无法识别潜在的解决方案。接受的答案没有帮助。我已经使用64位系统并使用最新的Canopy稳定版本(1.5.5 64位,使用Python 2.7.10)。
避免此MemoryError问题的最快和/或最pythonic方法是什么?
答案 0 :(得分:2)
为什么不将你的正确文件读入pandas(甚至是简单的字典),然后使用csv
模块遍历左侧文件来读取,扩展和写入每一行?处理时间是一个重要的约束(与开发时间相比)?
答案 1 :(得分:2)
这种方法最终起作用了。这是我的代码模型:
import csv
idata = open("KEY_ABC.csv","rU")
odata = open("KEY_XYZ.csv","rU")
leftdata = csv.reader(idata)
rightdata = csv.reader(odata)
def gen_chunks(reader, chunksize=1000000):
chunk = []
for i, line in enumerate(reader):
if (i % chunksize == 0 and i > 0):
yield chunk
del chunk[:]
chunk.append(line)
yield chunk
count = 0
d1 = dict([(rows[3],rows[0]) for rows in rightdata])
odata.seek(0)
d2 = dict([(rows[3],rows[1]) for rows in rightdata])
odata.seek(0)
d3 = dict([(rows[3],rows[2]) for rows in rightdata])
for chunk in gen_chunks(leftdata):
res = [[k[0], k[1], k[2], k[3], k[4], k[5], k[6],
d1.get(k[6], "NaN")] for k in chunk]
res1 = [[k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7],
d2.get(k[6], "NaN")] for k in res]
res2 = [[k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7], k[8],
d3.get(k[6], "NaN")] for k in res1]
namestart = "FINAL_"
nameend = ".csv"
count = count+1
filename = namestart + str(count) + nameend
with open(filename, "wb") as csvfile:
output = csv.writer(csvfile)
output.writerows(res2)
通过将左侧数据集拆分为块,将每个非键列的右侧数据集转换为一个字典,并通过向左侧数据集添加列(使用词典和键匹配填充它们),脚本设法执行整个左连接大约四分钟没有内存问题。
还要感谢用户miku在this post的评论中提供了块生成器代码。
那说:我非常怀疑这是最有效的方法。如果有人提出改进这种方法的建议,请离开。
答案 2 :(得分:0)
正如另一个问题"Large data" work flows using pandas所示,dask(http://dask.pydata.org)可能是一个简单的选择。
简单示例
import dask.dataframe as dd
df1 = dd.read_csv('df1.csv')
df2 = dd.read_csv('df2.csv')
df_merge = dd.merge(df1, df2, how='left')