【问题标题】:speeding up parsing of files加快文件解析
【发布时间】:2011-02-28 05:19:39
【问题描述】:

以下函数将一个 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)

回应cmets:

我知道有一个 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 将字段解析为它们的类型?

谢谢。

谢谢。

【问题讨论】:

  • 你知道有一个csv module 对吗?
  • 如果有deadbeef,那么显然它是一个基数为16的整数,对吧? Python 不会猜测,你也不应该。

标签: python csv numpy scipy


【解决方案1】:

熊猫呢?

import pandas as pd

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

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

【讨论】:

    【解决方案2】:
    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)]
    

    【讨论】:

    • 非常感谢。关于这个的另一个问题:如何让 DictWriter 从我读入的 csv 文件中序列化出阅读器?我必须为此编写自定义方法吗?
    • @user248237: writer.writerows(data) 序列化字典列表。如果您的数据包含非 ascii 字符串,那么您需要类似于来自 docs.python.org/library/csv.html#examplesUnicodeWriter 的自定义编写器
    【解决方案3】:

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

    • 为什么需要字典?密钥存储在每个 dict 实例中,这会增加内存消耗。

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

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

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

    【讨论】:

    • 我同意它不应该全部加载到内存中——这很好,而且 csv.DictReader 不会这样做。但我确实认为 dictreader 绝对应该认识到,当一个字段的所有条目看起来像 5.34 或 0.05 时,它应该是一个浮点数,而不是一个字符串,并且在我的文件中它没有这样做(嗅探能够检测到分隔符/行终止符,但不是那个。)我怎样才能让它推断出明显的类型?
    • 另外:我不想单独转换每一行——我同意每一列的类型应该是固定的,但我无法让 DictReader 推断出一列具有所有浮点数,即使所有值在文件的那一列中是浮点数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 2016-03-09
    • 2010-12-27
    • 1970-01-01
    相关资源
    最近更新 更多