【问题标题】:Is there a better way to improve the concat speed?有没有更好的方法来提高 concat 速度?
【发布时间】:2021-01-13 02:49:50
【问题描述】:

我是韩国的一名学生,我正在使用 python 来分析期权数据(金融)。 我正在寻找一种更好的方法来加快我的 python 代码的性能。

目标数据为期权的交易记录(每分钟),时间段为2015年至2019年。 因为数据被分成1227个(5年内的工作日数)个文件(txt),所以我尝试将所有1227个文件串联起来,以尽量减少访问内存的次数。这是因为我将重复使用结果文件(连接文件 = 预处理文件)并且访问每个分离的文件花费了太多时间。以下是我的部分代码。

#file_name is list type and it contains all names of the 1227 day files ordered by date

result_df = pd.DataFrame()
for f in file_name: 

    data_opt = pd.read_csv(location + f, header = None, sep = "\t")

    #do something
    #...
    #...

    oneday_df = pd.concat([minute_call, minute_put], axis = 0) #result of the processing one day data

    result_df = pd.concat([result_df, oneday_df], axis = 0)

result_df.to_csv()

此代码有效,我可以获得正确的结果。但是,我可以看到随着时间的推移速度变慢了。这意味着我的代码在处理早期数据时运行速度很快,但在处理后期数据时速度变慢。有没有更好的方法来加快我的 python 代码的性能?

(对不起,我的英语笨拙,感谢您阅读所有问题)

【问题讨论】:

  • 您可以将result_df = pd.concat(...) 移出循环,方法是将所有oneday_df 保存到列表中,然后执行result_df = pd.concat(list_with_oneday_dfs, axis = 0)
  • 进行多个连续调用并不理想。您可以改为阅读解决类似问题的这个 stackoverflow 问题:stackoverflow.com/questions/20906474/… 和这个:stackoverflow.com/questions/57000903/…
  • 非常感谢!我学到了新的想法!我马上试试

标签: python pandas performance concatenation


【解决方案1】:

不要在内存中连接,而是保持输出 CSV 文件打开并在执行过程中分别将每个部分写入其中?

这样一来,您在内存中一次永远不会有超过一天的数据,不仅可以提高速度,还可以提高内存消耗。

类似:

with open('out_file.csv', 'w') as of:
    for i, f in enumerate(file_name): 

        data_opt = pd.read_csv(location + f, header = None, sep = "\t")

        #do something
        #...
        #...

        oneday_df = pd.concat([minute_call, minute_put], axis = 0) #result of the processing one day data

        is_first_part = (i == 0)
        oneday_df.to_csv(of, header=is_first_part)

【讨论】:

  • 非常感谢您的宝贵建议!我将编辑我的代码!
  • 您提供的方法显示出恒定且可接受的速度!谢谢萨比克!
【解决方案2】:

我认为与其在 for 循环中连接,不如将这些数据帧存储在列表中,并在 for 循环之后连接它们。

类似:

minute_something = []
for f in file_name: 

    data_opt = pd.read_csv(location + f, header = None, sep = "\t")

    #do something
    #...
    #...
        
    minute_something.append(minute_put)
    minute_something.append(minute_call) #result of the processing one day data

result_df = pd.concat(munute_something, axis=0)

【讨论】:

    【解决方案3】:

    我计时了两种方法来组合 1000 个 csv 文件和 100 行和 10 列

    • [19.50 秒] 在列表中收集数据帧并保存连接的数据帧
    • [09.84 s] 迭代追加到 csv 文件

    首先生成测试文件并在列表中获取文件名

    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame(np.random.rand(100,10))
    
    for i in range(1000):
        df.to_csv(f'../data/test/file{i:04d}.csv', index=False)
    
    import glob
    files = glob.glob('../data/test/file*.csv')
    

    然后我对这两种方法都进行了计时
    append 列出,concat 全部,to_csv

    %%time
    l = []
    for file in files:
        l.append(pd.read_csv(file))
    pd.concat(l).to_csv('../data/test/concat_files.csv', index=False)
    

    输出:

    CPU times: user 4.7 s, sys: 547 ms, total: 5.25 s
    Wall time: 19.5 s
    

    append模式转csv文件

    %%time
    pd.read_csv(files[0])[:0].to_csv('../data/test/append_files.csv', index=False)
    for file in files:
        pd.read_csv(file).to_csv('../data/test/append_files.csv', mode='a', header=False, index=False)
    

    输出:

    CPU times: user 8.09 s, sys: 1.19 s, total: 9.28 s
    Wall time: 9.84 s
    

    【讨论】:

    • 对比非常清晰!谢谢你的测量!我尝试了第二种方法,效果很好!
    猜你喜欢
    • 2013-04-04
    • 1970-01-01
    • 2016-11-21
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多