【问题标题】:Reading a CSV-file with repetitive headers读取带有重复标题的 CSV 文件
【发布时间】:2012-12-31 11:02:24
【问题描述】:

python中的csv module之前没用过,不过感觉用起来很方便。

问题是我尝试读取的 CSV 文件也时不时地在文件中包含标题(索引)。

类似这样的:

A, B, C, D, E, F
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6
A, B, C, D, E, F
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6
A, B, C, D, E, F
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6
1, 2, 3, 4, 5, 6

我可以按原样使用csv module,还是必须自己解析。

【问题讨论】:

  • 是否可以以编程方式区分标题行和普通行?如果是这样,怎么做?例如,可能标题行总是与第一个标题完全相同,并且列名将作为正常值无效。或者也许正常值总是整数,但标题行不是。或者……无论规则是什么,您都必须能够在编写代码之前声明它。

标签: python parsing csv


【解决方案1】:

您可以通过检查您是否只是阅读标题行来按原样使用它。例如,使用DictReader,您可以这样做:

with open('file.csv') as f:
    reader = csv.DictReader(f)
    lines = [row for row in reader
             if not all(k == v for k, v in row.iteritems())]

这将适用于您的示例文件的方式是:

  1. DictReader 构造函数读取第一个标题行,确定字段名为 "A", "B", "C", "D", "E", "F"。
  2. 遍历reader 然后返回像{"A": "1", "B": "2", ...} 这样的字典。
  3. lines 中的列表理解查看每一行字典。它首先会看到像{"A": "1", ...} 这样的字典。 all(k == v for k, v in row.iteritems()) 循环遍历行的键和值,设置例如k = "A" 和 v = "1"。无论它首先看到哪个取决于字典决定如何迭代,它都会看到k != v,因此all() 调用将是False,这意味着该行进入列表lines。李>
  4. 当它到达重复的标题行时,它会看到像{"A": "A", "B": "B", ...} 这样的字典。然后,由于键等于每个字典元素的值,all() 调用将返回True,列表推导中的条件将是False,这意味着该行不会进入最终列表。请注意,如果您的标题行可能有不同的间距,您需要先对键/值调用 .strip(),然后再在 all() 调用中比较它们。
  5. 最后,您的示例文件的lines 将等于[{"A": 1, "B": 2, ...}] * 9;重复的标题行已被删除。

如果您想逐行处理文件而不是一次将其读入一个列表,只需将lines 的列表理解更改为生成器表达式,方法是将[row for row ...] 更改为(row for row ...) .然后你可以循环lines,但循环后每一行都会被遗忘(就像你一开始就做了for row in reader)。

【讨论】:

  • 您能否详细说明一下这是如何工作的!由于单线,很难调试!
  • 添加了一些解释。但是,当您说“调试”时,您的意思是您在运行它时遇到了问题,还是在理解上遇到了问题?之前缺少),但它对我有用....
  • 我的分离正常形式器官(它以非自愿反射的形式分泌重构激素)告诉我... if any(k != v...
  • 我为此 +1。在实践中,标题行很可能很容易区分。例如,标题是字符串,如果一列需要一个数字,只检查这一列就足够了:如果值是标题字符串,那么它不是正常的行。此处介绍的方法不会花费太多时间,因为在大多数情况下(正常线),它会在第一次比较后退出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 2011-01-18
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多