使用Python编辑CSV文件时跳过标题


209

我正在使用以下引用的代码使用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但没有成功。

请帮助我解决这个问题。


Answers:


370

您的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)

22
还可以使用另一种方法for row in islice(reader, 1, None)-尽管不如next大多数简单的“跳过一行”作业显式,但要跳过多个标题行(或仅获取某些块等),这非常方便
Jon Clements

我会考虑使用try: writer.write(next(reader))... except StopIteration: # handle empty reader
乔恩·克莱门茨

@JonClements:也许吧。无需讲授try:/就足够了except:
马亭皮特斯

1
@JonClements:显式next迭代的优点是它是“免费的”;islice会包装reader永久增加的迭代开销(非常少)。可以使用consumefromitertools配方快速跳过许多值,而不必在随后的用法中添加换行符(islice如果带有a start而不是no)end,那么开销不会给您带来任何好处。
ShadowRanger

120

解决此问题的另一种方法是使用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'])

21
我觉得这是真正的答案,因为这个问题似乎是XY问题的一个例子。
MariusSiuram '16

3
DictReader绝对是必经之路
哈维尔·阿里亚斯

4
重要的是要注意,这仅在构造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
BuvinJ,

7

在做 row=1不会改变任何东西,因为您只会用循环的结果覆盖它。

您要next(reader)跳过一行。


我尝试将其更改为,for row in next(reader):但给我IndexError: string index out of range错误

在for循环之前使用它:next(reader); for row in reader:....
dlazesz,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.