加速解析文件

时间:2010-06-05 18:35:41

标签: python csv numpy scipy

以下函数将CSV文件解析为字典列表,其中列表中的每个元素都是一个字典,其中的值由文件的标头索引(假定为第一行。)

这个函数非常慢,对于一个相对较小的文件(少于30,000行)需要大约6秒钟。

我怎样才能加快速度?

def csv2dictlist_raw(filename, delimiter='\t'):
    f = open(filename)
    header_line = f.readline().strip()
    header_fields = header_line.split(delimiter)
    dictlist = []
    # convert data to list of dictionaries
    for line in f:
    values = map(tryEval, line.strip().split(delimiter))
    dictline = dict(zip(header_fields, values))
    dictlist.append(dictline)
    return (dictlist, header_fields)

回应评论:

我知道有一个csv模块,我可以像这样使用它:

data = csv.DictReader(my_csvfile, delimiter=delimiter)

这要快得多。但是,问题在于它不会自动将显然浮点数和整数的内容转换为数字,而是将它们作为字符串。我该如何解决这个问题?

使用“Sniffer”类对我不起作用。当我在我的文件上尝试它时,我收到错误:

File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/csv.py", line 180, in sniff
    raise Error, "Could not determine delimiter"
Error: Could not determine delimiter

如果显而易见,我怎样才能让DictReader将字段解析为它们的类型?

感谢。

感谢。

3 个答案:

答案 0 :(得分:3)

import ast

# find field types
for row in csv.DictReader(my_csvfile, delimiter=delimiter):
    break
else:
    assert 0, "no rows to process"
cast = {}
for k, v in row.iteritems():
    for f in (int, float, ast.literal_eval):
        try: 
            f(v)
            cast[k] = f
            break
        except (ValueError, SyntaxError):
            pass
    else: # no suitable conversion
        cast[k] = lambda x: x.decode(encoding)

# read data
my_csvfile.seek(0)

data = [dict((k.decode(encoding), cast[k](v)) for k, v in row.iteritems())
        for row in csv.DictReader(my_csvfile, delimiter=delimiter)]

答案 1 :(得分:1)

我发现您的代码有几个问题:

  • 你为什么需要dicts?密钥存储在每个dict实例中,这会耗尽内存消耗。

  • 您真的需要将所有实例保留在内存中,还是可以选择使用yield

  • 尝试转换每个值需要时间,在我的选项中没有任何意义。如果您的列的值为“abc”和“123”,则最后一个值应该是一个字符串。因此,列的类型应该是固定的,您应该明确转换。

  • 即使您想使用转换逻辑:使用csv模块并在之后转换值。

答案 2 :(得分:1)

熊猫怎么样?

import pandas as pd

# load everything in
df = pd.read_table(filename)

# coerce strings to numeric
df = df.convert_objects(convert_numeric=True)