加速文件解析

2 投票
3 回答
2027 浏览
提问于 2025-04-15 23:36

下面这个函数的作用是把一个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 个回答

1

那 pandas 呢?

import pandas as pd

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

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

我看到你的代码有几个问题:

  • 你为什么需要用字典?每个字典实例都存储了键,这样会占用很多内存。

  • 你真的需要把所有实例都放在内存里吗?用 yield 可能是个不错的选择。

  • 试图转换每个值会浪费时间,而且在我看来没有必要。如果你有一列的值是“abc”和“123”,那么最后一个值应该是字符串。所以一列的类型应该是固定的,转换应该明确进行。

  • 即使你想用自己的转换逻辑,也可以使用 csv 模块,然后再进行值的转换。

3

在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。比如说,当你在写代码时,可能会发现某个功能没有按照预期工作。这种情况可能是因为你没有正确使用这个工具,或者是因为你的代码中有一些小错误。

为了找到问题所在,通常我们会查看错误信息。这些信息就像是程序给我们的提示,告诉我们哪里出了问题。理解这些错误信息是解决问题的第一步。

此外,很多时候我们可以在网上找到其他人遇到类似问题的讨论,比如在StackOverflow这样的论坛上。这里有很多开发者分享他们的经验和解决方案,你可以从中获得灵感,找到解决自己问题的方法。

总之,遇到问题时不要慌张,先仔细查看错误信息,然后可以去网上查找相关的讨论和解决方案,这样你就能更快地解决问题了。

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)]

撰写回答