【问题标题】:Find number of columns in csv file查找csv文件中的列数
【发布时间】:2012-07-03 20:17:53
【问题描述】:

我的程序需要读取可能有 1,2 或 3 列的 csv 文件,并且需要相应地修改其行为。有没有一种简单的方法可以在迭代器运行之前检查列数而不“消耗”一行?以下代码是我能管理的最优雅的代码,但我更愿意在 for 循环开始之前运行检查:

import csv
f = 'testfile.csv'
d = '\t'

reader = csv.reader(f,delimiter=d)
for row in reader:
    if reader.line_num == 1: fields = len(row)
    if len(row) != fields:
        raise CSVError("Number of fields should be %s: %s" % (fields,str(row)))
    if fields == 1:
        pass
    elif fields == 2:
        pass
    elif fields == 3:
        pass
    else:
        raise CSVError("Too many columns in input file.")

编辑:我应该包含有关我的数据的更多信息。如果只有一个字段,它必须包含一个科学计数法的名称。如果有两个字段,第一个必须包含名称,第二个必须包含链接代码。如果存在三个字段,则附加字段包含指定名称当前是否有效的标志。因此,如果任何行有 1、2 或 3 列,则所有列都必须相同。

【问题讨论】:

  • 最好使用fields 而不是rows
  • @MarcodeWit 谢谢,当然应该是fields!我也同意您的观点,即并非所有行都必须具有相同数量的字段。在这种情况下,我决定如果遇到这样的行应该引发异常。

标签: python csv


【解决方案1】:

这似乎也有效:

import csv

datafilename = 'testfile.csv'
d = '\t'
f = open(datafilename,'r')

reader = csv.reader(f,delimiter=d)
ncol = len(next(reader)) # Read first line and count columns
f.seek(0)              # go back to beginning of file
for row in reader:
    pass #do stuff

【讨论】:

    【解决方案2】:

    我会建议这样一个简单的方法:

    with open('./testfile.csv', 'r') as csv:
         first_line = csv.readline()
         your_data = csv.readlines()
    
    ncol = first_line.count(',') + 1 
    

    【讨论】:

      【解决方案3】:

      您可以使用itertools.tee

      itertools.tee(iterable[, n=2])
      从 a 返回 n 个独立迭代器 单个可迭代。

      例如。

      reader1, reader2 = itertools.tee(csv.reader(f, delimiter=d))
      columns = len(next(reader1))
      del reader1
      for row in reader2:
          ...
      

      请注意,完成后删除对reader1 的引用很重要,否则tee 将不得不将所有行存储在内存中,以防您再次调用next(reader1)

      【讨论】:

        【解决方案4】:

        我会重建它如下(如果文件不是太大):

        import csv
        f = 'testfile.csv'
        d = '\t'
        
        reader = list(csv.reader(f,delimiter=d))
        fields = len( reader[0] )
        for row in reader:
            if fields == 1:
                pass
            elif fields == 2:
                pass
            elif fields == 3:
                pass
            else:
                raise CSVError("Too many columns in input file.")
        

        【讨论】:

        • @Martijn Pieters:这就是为什么我从有关文件大小的警告开始。 list 函数从迭代器中复制所有内容,因此只有小的 csv 文件是合适的。
        【解决方案5】:

        如果用户向您提供列数较少的 CSV 文件会怎样?是否使用默认值?

        如果是这样,为什么不用空值来扩展行呢?

        reader = csv.reader(f,delimiter=d)
        for row in reader:
            row += [None] * (3 - len(row))
            try:
                foo, bar, baz = row
            except ValueError:
                # Too many values to unpack: too many columns in the CSV
                raise CSVError("Too many columns in input file.")
        

        现在 bar 和 baz 至少为 None 并且异常处理程序将处理任何超过 3 个项目的行。

        【讨论】:

        • 这种方法的问题是每一行在每个字段中必须有一致的数据,但是数据很难验证。
        • 除了测试第一行的长度之外,我没有看到我的方法如何设置更多的一致性约束。此外,您没有告诉我们太多有关您的数据的信息;因此我的回答从一个问题开始。
        • 你是对的,我已经编辑了我的问题以包含更多关于数据的信息,并且还包括每行的一致性检查。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-11
        • 1970-01-01
        • 2015-06-11
        • 1970-01-01
        相关资源
        最近更新 更多