【问题标题】:Skip the headers when editing a csv file using Python使用 Python 编辑 csv 文件时跳过标题
【发布时间】:2012-12-24 19:23:30
【问题描述】:

我正在使用下面提到的代码来使用 Python 编辑 csv。代码中调用的函数构成了代码的上半部分。

问题:我希望下面提到的代码从第二行开始编辑 csv,我希望它排除包含标题的第一行。现在它只在第一行应用函数,我的标题行正在改变。

in_file = open("tmob_notcleaned.csv", "rb")
reader = csv.reader(in_file)
out_file = open("tmob_cleaned.csv", "wb")
writer = csv.writer(out_file)
row = 1
for row in reader:
    row[13] = handle_color(row[10])[1].replace(" - ","").strip()
    row[10] = handle_color(row[10])[0].replace("-","").replace("(","").replace(")","").strip()
    row[14] = handle_gb(row[10])[1].replace("-","").replace(" ","").replace("GB","").strip()
    row[10] = handle_gb(row[10])[0].strip()
    row[9] = handle_oem(row[10])[1].replace("Blackberry","RIM").replace("TMobile","T-Mobile").strip()
    row[15] = handle_addon(row[10])[1].strip()
    row[10] = handle_addon(row[10])[0].replace(" by","").replace("FREE","").strip()
    writer.writerow(row)
in_file.close()    
out_file.close()

我试图通过将row 变量初始化为1 来解决这个问题,但没有成功。

请帮我解决这个问题。

【问题讨论】:

标签: python python-2.7 csv


【解决方案1】:

执行row=1 不会改变任何内容,因为您只会用循环的结果覆盖它。

您想通过next(reader) 跳过一行。

【讨论】:

  • 我尝试将其更改为for row in next(reader):,但它给了我IndexError: string index out of range 错误
  • 在for循环之前使用它:next(reader); for row in reader: ....
【解决方案2】:

您的 reader 变量是可迭代的,通过循环它可以检索行。

要让它在循环之前跳过一项,只需调用 next(reader, None) 并忽略返回值。

您还可以稍微简化代码;使用打开的文件作为上下文管理器来自动关闭它们:

with open("tmob_notcleaned.csv", "rb") as infile, open("tmob_cleaned.csv", "wb") as outfile:
   reader = csv.reader(infile)
   next(reader, None)  # skip the headers
   writer = csv.writer(outfile)
   for row in reader:
       # process each row
       writer.writerow(row)

# no need to close, the files are closed automatically when you get to this point.

如果您想将标头写入未处理的输出文件,这也很简单,将next() 的输出传递给writer.writerow()

headers = next(reader, None)  # returns the headers or `None` if the input is empty
if headers:
    writer.writerow(headers)

【讨论】:

  • 另一种方法是使用for row in islice(reader, 1, None) - 尽管对于大多数简单的“跳过一行”作业、跳过多个标题行(或只获取某些块等)来说,不如next 明确... ) 这很方便
  • 我会考虑使用try: writer.write(next(reader))... except StopIteration: # handle empty reader
  • @JonClements:也许吧。这很有效,无需教授try: / except:
  • @JonClements:显式next 迭代的优势在于它是“免费的”; islice 将包装 reader 永远为每次迭代增加(公认的非常少量)开销。 consume recipe from itertools 可用于快速跳过许多值,而无需为后续使用添加包装,在islice 将具有start 但没有end 的情况下,因此开销不会为您带来任何好处。
【解决方案3】:

解决此问题的另一种方法是使用 DictReader 类,它“跳过”标题行并使用它来允许命名索引。

给定“foo.csv”如下:

FirstColumn,SecondColumn
asdf,1234
qwer,5678

像这样使用 DictReader:

import csv
with open('foo.csv') as f:
    reader = csv.DictReader(f, delimiter=',')
    for row in reader:
        print(row['FirstColumn'])  # Access by column header instead of column number
        print(row['SecondColumn'])

【讨论】:

  • 我觉得这是真正的答案,因为这个问题似乎是XY problem 的一个例子。
  • DictReader 绝对是要走的路
  • 重要的是要注意,这只有在构造 DictReader 时省略字段名称参数时才有效。根据文档:If the fieldnames parameter is omitted, the values in the first row of the file f will be used as the fieldnames.docs.python.org/2/library/csv.html
【解决方案4】:

受 Martijn Pieters 回应的启发。

如果您只需要从csv文件中删除标题,则使用标准Python文件I/O库编写可以更有效地工作,避免使用CSV Python库编写:

with open("tmob_notcleaned.csv", "rb") as infile, open("tmob_cleaned.csv", "wb") as outfile:
   next(infile)  # skip the headers
   outfile.write(infile.read())

【讨论】:

  • 您似乎忽略了 Martijn 的答案中的 # process each row 部分,它代表了操作员想要对行进行的所有操作,以及操作员想要 csv-文件作为输出?当然,您可以完全避免使用csv 模块。但有什么意义,它来自 standard 库?
  • 就我而言,我只想从csv 文件中删除标题,我不想处理任何内容。出于这个原因,我使用标准库编写,因为它更快。我将编辑我的评论以使其更加清晰。
  • 我明白了。在这种情况下,您根本不需要 csv 模块:只需 next(infile) 而不实例化 csv.reader 就可以了(open 的输出也是一个迭代器)。
【解决方案5】:

用 next() 简单地迭代一次

with open(filename) as file:

    csvreaded = csv.reader(file)
    header = next(csvreaded)

    for row in csvreaded:
        empty_list.append(row) #your csv list without header  

或在阅读器对象的末尾使用 [1:]

with open(filename) as file:

    csvreaded = csv.reader(file)
    header = next(csvreaded)

    for row in csvreaded[1:]:
        empty_list.append(row) #your csv list without header  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 2016-05-29
    相关资源
    最近更新 更多