【问题标题】:efficient way to extract few lines of data from a large csv data file in python从python中的大型csv数据文件中提取几行数据的有效方法
【发布时间】:2015-06-25 08:51:51
【问题描述】:

我有大量的 csv 数据文件,每个数据文件包含一个股票数天的报价数据,格式如下:

 ticker  DD/MM/YYYY    time         bid      ask
  XXX,   19122014,  08:00:08.325,  9929.00,9933.00
  XXX,   19122014,  08:00:08.523,  9924.00,9931.00
  XXX,   19122014,  08:00:08.722,  9925.00,9930.50
  XXX,   19122014,  08:00:08.921,  9924.00,9928.00
  XXX,   19122014,  08:00:09.125,  9924.00,9928.00
  …
  XXX,   30122014,  21:56:25.181,  9795.50,9796.50
  XXX,   30122014,  21:56:26.398,  9795.50,9796.50
  XXX,   30122014,  21:56:26.598,  9795.50,9796.50
  XXX,   30122014,  21:56:26.798,  9795.50,9796.50
  XXX,   30122014,  21:56:28.896,  9795.50,9796.00
  XXX,   30122014,  21:56:29.096,  9795.50,9796.50
  XXX,   30122014,  21:56:29.296,  9795.50,9796.00
  …

我需要提取时间在一定范围内的任何数据行,例如:09:00:00 到 09:15:00。我目前的解决方案是简单地将每个数据文件读入数据框,按时间排序,然后使用 searchsorted 查找 09:00:00 到 09:15:00。如果性能不是问题并且我没有 1000 个文件等待处理,它可以正常工作。关于如何提高速度的任何建议?提前感谢您的帮助!!!

【问题讨论】:

  • 鉴于您对解决方案的描述,您至少可以通过在读取它们时处理这些行而不是读取整个文件,进行排序然后处理它们来获得一些速度。因此,如果您只是在阅读时检查每行的时间是否在有效范围内,您将保存整个排序步骤,这可能非常慢。
  • 我们在这里谈论多大?您可以将所有csv读入df列表,然后concat它们都将索引设置为时间,然后使用df.loc[(df.index.time > '09:00:00') & (df.index.time < '09:15:00')]进行过滤,在加载它们时,您可以对索引进行排序并丢弃那些没有的反正有那个范围
  • 是的,它肯定会起作用,但它不是和我一样慢吗?目前我正在处理大约 4 GB 的数据量,我可能会处理 80GB 的数据量。

标签: python performance csv pandas


【解决方案1】:

简短回答:将您的数据放入 SQL 数据库中,并为“时间”列指定索引。你无法用 CSV 文件打败它——不管是否使用 Pandas。

在不更改 CSV 文件的情况下,稍微快一点,但在读取行时过滤行并不多 - 并且只在内存中保留对您感兴趣的行。

因此,这样的函数可以完成这项工作,而不是仅仅将整个 CSV 存入内存:

import csv

def filter_time(filename, mintime, maxtime):
    timecol = 3
    reader = csv.reader(open(filename))
    next(reader)
    return [line for line in reader if mintime <= line[timecol] <= maxtime]

这个任务很容易瘫痪——我猜你可以在最大化设备上的 I/O 之前让这个任务的一些实例同时运行。一种轻松的方法是使用lelo Python 包——它只是为您提供一个@paralel 装饰器,使给定函数在调用时在另一个进程中运行,并为结果返回一个惰性代理。

但这仍然需要阅读所有内容 - 我认为 SQL 解决方案应该至少快一个数量级。

【讨论】:

    【解决方案2】:

    我的解决方案是逐行读取并仅保存通过过滤器的内容:

    with open('filename.csv') as fin:
        with open('fileout.csv', 'w') as fout:
            while True:
                line = fin.readline()
                if not line:
                    break
                time_x = line.rstrip('\n').split(',')[2]
                # some parsing of time to do properly
                if a< time_x < b:
                    fout.write(line)
    

    【讨论】:

    • 您应该在读取 csv 文件时使用 stdlib csv 模块。在大多数情况下,像您在此处所做的那样手动解析是可行的,但容易出错(例如,在引用的 CSV 值上可能包含“,”本身),并且当您期望最少时,这些都会让您失望。此外,由于这里的问题是性能问题,默认情况是标准库上的集成调用将比手动处理字符串更快。 (必须正确分析这两种方法才能确定,但​​以此为经验法则)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 2021-11-18
    • 2022-06-11
    • 1970-01-01
    • 2012-06-23
    • 2018-12-24
    • 1970-01-01
    相关资源
    最近更新 更多