2017-08-16 17 views
2

由于数据量巨大,我们使用熊猫来处理数据,但出现了一个非常奇怪的现象。伪代码如下所示:具有块大小选项的pandas.read_csv函数的奇怪索引机制

reader = pd.read_csv(IN_FILE, chunksize = 1000, engine='c') 
for chunk in reader: 
    result = [] 
    for line in chunk.tolist(): 
     temp = complicated_process(chunk) # this involves a very complicated processing, so here is just a simplified version 
     result.append(temp) 
    chunk['new_series'] = pd.series(result) 
    chunk.to_csv(OUT_TILE, index=False, mode='a') 

我们可以确认每个循环的结果不为空。但只有在循环的第一次,chunk['new_series'] = pd.series(result)行有结果,其余都是空的。因此,只有输出的第一个块包含new_series,其余都是空的。

我们错过了什么吗?提前致谢。

回答

3

你应该在你的循环之上声明result,否则你只是用每个块重新初始化它。

result = [] 
for chunk in reader: 
    ... 

你以前的方法在功能上等同于:

for chunk in reader: 
    del result # because it is being re-assigned on the following line. 
    result = [] 
    result.append(something) 
print(result) # Only shows result from last chunk in reader (the last loop). 

另外,我建议:

chunk = chunk.assign(new_series=result) # Instead of `chunk['new_series'] = pd.series(result)`. 

我假设你正在做的line可变的东西在你for loop,即使它在上面的示例中没有使用。

+1

非常感谢。是的,你的建议奏效了。但我不明白为什么移动result = []以外的作品。这对我来说很尴尬。你能详细说一下吗?非常感谢! – acepor

+0

感谢您的解释。但这并不是造成问题的原因。当我们追踪每个块的索引时,我发现它们不是单独的。我们假设每个块都会从0开始索引,但实际上它不是。在这种情况下,每个块的索引是整个CSV的一个子集,因此它们的索引源自CSV。这是造成问题的原因。在上面的例子中,'pandas.to_csv'只写入第一个块的结果,而不是最后一个块。但我仍然会感谢你的灵感;否则,我真的不知道如何解决这个问题。 – acepor

+0

您是否使用我的'chunk = chunk.assign(new_series = result)'建议?我不认为你会有这个问题。 – Alexander

1

一个更好的解决办法是这样的:

reader = pd.read_csv(IN_FILE, chunksize = 1000, engine='c') 
for chunk in reader: 
    result = [] 
    for line in chunk.tolist(): 
     temp = complicated_process(chunk) # this involves a very complicated processing, so here is just a simplified version 
     result.append(temp) 
    new_chunk = chunk.reset_index() 
    new_chunk = new_chunk.assign(new_series=result) 
    new_chunk.to_csv(OUT_TILE, index=False, mode='a') 

注意:每个块的指标是不是个人,而是导出整个文件。如果我们从每个循环追加一个新的系列,块将继承整个文件的索引。因此,每个块和新系列的索引不匹配。

@亚历山大解决方案的工作,但result可能会变得巨大,所以它会占用太多的内存。

这里的新解决方案将通过执行new_chunk = chunk.reset_index()来重置每个块的索引,并且result将在每个循环内重置。这节省了大量的内存。