将 1300 个数据帧合并为一个帧变得非常慢

Posted

技术标签:

【中文标题】将 1300 个数据帧合并为一个帧变得非常慢【英文标题】:Merging 1300 data frames into a single frame becomes really slow 【发布时间】:2021-01-30 23:01:05 【问题描述】:

我在一个目录中有 1300 个 csv 文件。

每个文件的第一列都有一个日期,然后是过去 20-30 年的每日数据,这些数据跨越另外 8 列。

像这样, 数据1.csv

Date source1 source2 source3 source4 source5 source6 source 7 source 8

我有 1300 个唯一命名的文件。

我正在尝试使用这样的熊猫将所有这些合并到一个数据帧中

import pandas as pd 
frame = pd.DataFrame()

length = len(os.listdir(filepath))
for filename in os.listdir(filepath):
    file_path = os.path.join(filepath, filename)
    print(length,end=" ")
    df = pd.read_csv(file_path,index_col=0)
    df = pd.concat([df[[col]].assign(Source=f'filename[:-4]-col').rename(columns=col: 'Data') for col in df])
    frame = frame.append(df)
    length-=1

但是在第 300 个文件左右,我有大约 1200 万行,我的代码确实变慢了......

有没有办法在我的计算机内存不足之前加快速度。

我的目标实际上是拥有一个 30 年的日期数为 1+ (1300x8) 的海量数据框。

【问题讨论】:

(a) 您是否需要一次在内存中存储 12M+ 行? (b) 你看过Dask 吗? (c) 是时候寻找数据库解决方案了? 我实际上想合并所有帧 Column wise 有一个巨大的帧,其中只有日期是索引,所以它看起来像这样 Date data1-source1 data2-source2... data2-source1 data2-source2... 等等,但是当我尝试按列合并它时,我也用完了空间 @CodeDifferent 你能给我推荐任何数据库解决方案,让我保留一个庞大的列式数据库,我想要索引的日期时间序列,这意味着 30 年的每日日期,我想能够添加任意数量的新数据列 【参考方案1】:

循环变慢的原因是因为在每个.append(),数据帧必须创建一个副本以分配更多内存,如here 所述。

如果你的记忆可以全部容纳,你可以先用所有数据框填充一个固定大小(1300)的列表,然后使用df = pd.concat(list_of_dataframes),这可能会避免你遇到的问题现在有。您的代码可以这样调整:

import pandas as pd 
lst = [None for _ in range(1300)] # Creates empty list

for i, filename in enumerate(os.listdir(filepath)):
    file_path = os.path.join(filepath, filename)
    df = pd.read_csv(file_path,index_col=0)
    df = pd.concat([df[[col]].assign(Source=f'filename[:-4]-col').rename(columns=col: 'Data') for col in df])
    lst[i] = df
    

frame = pd.concat(lst)

【讨论】:

以上是关于将 1300 个数据帧合并为一个帧变得非常慢的主要内容,如果未能解决你的问题,请参考以下文章

将数据帧字典合并为 1 个单个数据帧

基于部分startswith匹配合并两个数据帧

如何将2个时间序列数据(宽表)合并为1个数据帧(宽表)?

无法合并2个数据帧

如何将 3 个 Pandas 数据帧合并到第 4 个数据帧以匹配列值名称?

如何根据多个条件将 1 个 pandas 数据帧合并或组合到另一个数据帧