【问题标题】:Parse a large CSV file with two different line formats in Python 2.7 with memory constraints?在具有内存限制的 Python 2.7 中解析具有两种不同行格式的大型 CSV 文件?
【发布时间】:2017-04-25 02:40:33
【问题描述】:

我有一组需要在 Python 2.7 中读取的文件(一个 ~10GB 文件分成多个文件,因此每个文件约 1GB)。文件格式是这样的:

1|KEY1|A |B        |01/01/2016|   |
2|KEY1| |LINEINDEX1|C            |D  |E                  | 123.000| 456.000| 789.1250|000100000.00|000100000.70|100|01/2016| 001|100|01/2016|050|050|01|001|100|F  |G            |H |1|I|J |   |K  |L    |M  |       |   |   |        |        |   |   |    |        |   |       |   |   |        |        |        |        |    |             |    |        |                          |  |              |           |   |              |   |   |  |  |        |        |       |   |   |   |   |             |        |              |   |       |       |   |   |   |   |       |         |   |
2|KEY1| |LINEINDEX2|C            |D  |E                  | 123.000| 456.000| 789.1250|000100000.00|000100000.70|100|01/2016| 001|100|01/2016|050|050|01|001|100|F  |G            |H |1|I|J |   |K  |L    |M  |       |   |   |        |        |   |   |    |        |   |       |   |   |        |        |        |        |    |             |    |        |                          |  |              |           |   |              |   |   |  |  |        |        |       |   |   |   |   |             |        |              |   |       |       |   |   |   |   |       |         |   
2|KEY1| |LINEINDEX3|C            |D  |E                  | 123.000| 456.000| 789.1250|000100000.00|000100000.70|100|01/2016| 001|100|01/2016|050|050|01|001|100|F  |G            |H |1|I|J |   |K  |L    |M  |       |   |   |        |        |   |   |    |        |   |       |   |   |        |        |        |        |    |             |    |        |                          |  |              |           |   |              |   |   |  |  |        |        |       |   |   |   |   |             |        |              |   |       |       |   |   |   |   |       |         |   |
2|KEY1| |LINEINDEX4|C            |D  |E                  | 123.000| 456.000| 789.1250|000100000.00|000100000.70|100|01/2016| 001|100|01/2016|050|050|01|001|100|F  |G            |H |1|I|J |   |K  |L    |M  |       |   |   |        |        |   |   |    |        |   |       |   |   |        |        |        |        |    |             |    |        |                          |  |              |           |   |              |   |   |  |  |        |        |       |   |   |   |   |             |        |              |   |       |       |   |   |   |   |       |         |   |    
1|KEY2|A |B        |01/01/2016|   |
2|KEY2| |LINEINDEX5|C            |D  |E                  | 123.000| 456.000| 789.1250|000100000.00|000100000.70|100|01/2016| 001|100|01/2016|050|050|01|001|100|F  |G            |H |1|I|J |   |K  |L    |M  |       |   |   |        |        |   |   |    |        |   |       |   |   |        |        |        |1       |    |             |    |        |                          |  |              |           |   |              |   |   |  |  |        |        |       |   |   |   |   |             |N       |              |   |       |       |   |   |   |   |       |         |   |    
2|KEY2| |LINEINDEX6|C            |D  |E                  | 123.000| 456.000| 789.1250|000100000.00|000100000.70|100|01/2016| 001|100|01/2016|050|050|01|001|100|F  |G            |H |1|I|J |   |K  |L    |M  |       |   |   |        |        |   |   |    |        |   |       |   |   |        |        |        |4       |    |             |    |        |                          |  |              |           |   |              |   |   |  |  |        |        |       |   |   |   |   |             |O       |              |   |       |       |   |   |   |   |       |         |   |

2 开头的行可以无限重复以获取唯一的LINEINDEX# 值,然后下一行将以1 开头以获取新的KEY 项目(其后是自己的行2,以及很快)。我需要能够基于多个KEYs 有效地生成数据类型2 的表,所以我实际上根本不需要行1。空白字段中可能有也可能没有数据,所以我需要捕获那里的所有内容。

围绕这些数据的大多数程序都使用 Pandas,所以我尽量坚持这一点。我的计划是将这些文件解析为 HDF5 文件,并根据需要从中创建表。我不确定这是否是解决手头问题的最佳方法,因此欢迎任何有关替代方案的建议。目前,此处理是通过 ffdf 在 R 中完成的,但必须将其移至 Python。

我无法逐行读取这些文件(几乎立即弹出内存不足)以删除/忽略行1。我尝试了 Pandas read_csvcomment='1',将这些行视为“cmets”并忽略它们,但我得到了 CParserError,这似乎比基于其他帖子的任何内容都更像一个错误(我尝试跳过第一行正如其他人针对该错误所建议的那样,但它没有解决问题)。

pandas.io.common.CParserError: Error tokenizing data. C error: Expected 4 fields in line 504, saw 14

如果我在没有指定数据类型(我有)的情况下处理文件,我会遇到性能问题,例如:

sys:1: DtypeWarning: Columns (21) have mixed types. Specify dtype option on import or set low_memory=False.

那么,在转换to_hdf时,类似的性能问题:

C:\Python27\lib\site-packages\pandas\core\generic.py:1138: PerformanceWarning: 
your performance may suffer as PyTables will pickle object types that it cannot map directly to c-types

什么是最好的方法要么忽略以1 all-together 开头的行,要么以某种方式指定两个不同的 dType 映射,而不会耗尽内存,每次我尝试逐行处理时都会发生这种情况线基础?有没有更好的方法来存储这些数据以根据KEYs 的列表查询订单项2

现在,代码很简单:

for input_file in os.listdir(input_path):
            file_path = input_path + '\\' + input_file
            data = pd.read_csv(file_path, sep='|')
            data.to_hdf(self.outputs_path + '\converted.h5', 'converted_table')

【问题讨论】:

  • 您将需要发布更长的输入数据样本——人们无法弄清楚它是如何在那里的,并且您希望能够以一种有意义的方式从您的仅文字描述。 (文本“LINEINDEX”是改变还是固定?“KEY”是否在每一行重复?非“1”行上的“KEY”后面的单元格包含您想要的标识符?
  • 总而言之,赌注建议是清理这些文件,然后加载一个数据框架并创建一个行为良好的 CSV 文件 - 您可以在第二遍中使用该文件来满足您的处理需求。
  • 请贴出您到目前为止所做尝试的代码。

标签: python python-2.7 pandas pytables hdfstore


【解决方案1】:

这将提取管道之间的任何数据,没有空格,并将该信息转储到一个新文件中。它只会写出包含字符串'LINEINDEX' 的行,如果管道之间的值全是空格,则忽略它。如果您需要保留管道之间的空值,请从列表推导中删除 if 子句 (if x.replace(' ',''))。

with open('/path/to/in_file.csv', 'r') as fp:
    with open('/path/to/out_file.csv', 'w') as fp2:
        for line in fp:
            if 'LINEINDEX' in line:
                out = [x.replace(' ','') for x in line.strip().split('|')
                       if x.replace(' ','')]
                fp2.write(','.join(out)+'\n')

这应该没有内存问题,因为每次读取和写入每个文件,而不是将整个文件加载到内存中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多