Python并发追加DataFrame到空DataFrame,仅返回最后一个结果的问题
解决Python并发运行函数合并DataFrame的问题
先帮你捋捋代码里的问题:你每次循环执行df = newData.append(file, ignore_index=True),但**newData自始至终都是空的DataFrame**,所以每次append都是把空DataFrame和当前任务返回的file合并,循环结束后df自然只会保留最后一次的结果。另外要提一句,pd.DataFrame.append已经被官方弃用了,现在更推荐用pd.concat来合并DataFrame。
正确的思路是先把所有并发任务返回的DataFrame收集到一个列表里,然后一次性合并——这种方式不仅逻辑正确,效率也远高于循环append(循环append会反复创建新对象,数据量大时性能很差)。
修正后的代码如下:
import concurrent.futures import pandas as pd import time import os # 用来获取CPU核心数,合理设置进程数 def putIndf(file): listSel = getline(file) datFram = savetoDataFrame(listSel) return datFram # datatype : dataframe def main(): # 先通过并发执行,收集所有任务返回的DataFrame到列表 with concurrent.futures.ProcessPoolExecutor(max_workers=os.cpu_count()) as executor: # executor.map会按fileList的顺序返回每个任务的结果 df_list = list(executor.map(putIndf, fileList)) # 一次性合并所有DataFrame newData = pd.concat(df_list, ignore_index=True) return newData if __name__ == '__main__': # 这里替换成你的实际文件列表 fileList = ["file1.txt", "file2.txt", ...] final_df = main()
还有几个细节要注意:
max_workers不用设成30这么大,ProcessPoolExecutor的最优值一般是CPU核心数(os.cpu_count()),过多的进程会因为上下文切换降低运行效率。- 确保
getline和savetoDataFrame能被序列化(多进程需要把函数和数据传给子进程),如果里面有无法序列化的对象,可能会触发报错。 - 如果不同任务返回的DataFrame列结构不一致,
pd.concat会自动补NaN;要是你只想保留列一致的部分,可以加上join='inner'参数。
要是你非得在并发过程中逐步合并(非常不推荐,多进程共享数据复杂度高、效率低),需要用到进程安全的队列或共享内存,但这种方案完全没必要,优先推荐上面的「先收集再合并」方式。
内容的提问来源于stack exchange,提问作者elisa
相关产品推荐
相关产品推荐

