处理CSV数据时如何忽略第一行数据?


113

我要Python从一列CSV数据中打印最少的数字,但是第一行是列号,我不希望Python考虑到第一行。如何确定Python忽略第一行?

到目前为止,这是代码:

import csv

with open('all16.csv', 'rb') as inf:
    incsv = csv.reader(inf)
    column = 1                
    datatype = float          
    data = (datatype(column) for row in incsv)   
    least_value = min(data)

print least_value

您还能说明自己在做什么,而不仅仅是给出代码吗?我对Python非常陌生,并希望确保我了解所有内容。


5
您是否知道您只是在创建一个生成器,该生成器1.0将为文件中的每一行返回a ,然后取最小值即可1.0
Wooble 2012年

@Wooble从技术上讲,它是的重要生成器1.0。:)
Dougal 2012年

@Wooble的好收获-... datatype(row[column]...我想是OP想要达到的目标
Jon Clements

我让某人为我编写了该代码,却没有抓住,所以谢谢哈哈!

Answers:


106

您可以使用csv模块Sniffer类的实例来推断CSV文件的格式,并检测是否存在标头行以及next()仅在必要时才跳过第一行的内置函数:

import csv

with open('all16.csv', 'r', newline='') as file:
    has_header = csv.Sniffer().has_header(file.read(1024))
    file.seek(0)  # Rewind.
    reader = csv.reader(file)
    if has_header:
        next(reader)  # Skip header row.
    column = 1
    datatype = float
    data = (datatype(row[column]) for row in reader)
    least_value = min(data)

print(least_value)

由于在您的示例中datatypecolumn都进行了硬编码,因此row像这样处理起来会更快一些:

    data = (float(row[1]) for row in reader)

注意:以上代码适用于Python3.x。对于Python 2.x,使用以下行来打开文件而不是显示的内容:

with open('all16.csv', 'rb') as file:

2
相反has_header(file.read(1024)),写起来有意义has_header(file.readline())吗?我看到了很多,但是我不明白如何has_reader()从CSV文件的一行中检测出是否有标题...
Anto

1
@Anto:我的答案中的代码基于文档中的“嗅探器使用示例” ,因此我认为这是规定的方法。我同意这样做一行数据的基础上,似乎并不像它会永远是足够的数据来做出这样的决定,但我后来不知道怎么Sniffer作品没有描述。FWIW我从未见过has_header(file.readline())使用过,即使它在大多数时间都能奏效,但由于上述原因,我对这种方法还是非常怀疑的。
martineau

感谢您的输入。不过,似乎使用会file.read(1024) 在python的csv lib:中产生错误。例如,也请参见此处
安托

@Anto:我从来没有遇到过这样的错误-毕竟1024字节不是很多内存-基于这个答案收到的支持票(以及成千上万个),对于其他许多人来说也不是问题。阅读并遵循文档的人员)。由于这些原因,我强烈怀疑其他原因导致了您的问题。
martineau

从切换到时readline(),我遇到了完全相同的错误read(1024)。到目前为止,我仅设法找到改用readline解决csv.dialect问题的人员。
安托

75

要跳过第一行,只需调用:

next(inf)

Python中的文件是行上的迭代器。


22

在类似的用例中,我不得不在具有实际列名的行之前跳过烦人的行。该解决方案效果很好。首先阅读文件,然后将列表传递给csv.DictReader

with open('all16.csv') as tmp:
    # Skip first line (if any)
    next(tmp, None)

    # {line_num: row}
    data = dict(enumerate(csv.DictReader(tmp)))

谢谢Veedrac。很高兴在这里学习,您能否建议可以解决您引用的问题的修改?我的解决方案可以完成工作,但看起来可以进一步改进吗?
马丁(Maarten)

1
我给了您一个编辑,用应该相同(未经测试)的代码替换代码。如果与您的意思不符,请随时还原。我仍然不确定为什么要制作data字典,这个答案也不会在接受的字典上添加任何内容。
Veedrac,2015年

谢谢Veedrac!看起来确实非常有效。我发布了答案,因为被接受的答案对我不起作用(现在不记得原因了)。定义data = dict()然后立即填充它(与您的建议相比)会有什么问题?
马滕

1
进行填写并没有data = dict(),但是效率低下,而且不是惯用的。另外,甚至应该使用dict文字({}enumerate
Veedrac

1
FWIW,@Veedrac如果您想确定已收到通知,则应该回复我的帖子,尽管Stack Overflow似乎可以从用户名中猜测出来。(我不会写,@Maarten因为默认情况下会通知应答者。)
Veedrac,2015年

21

python cookbook借来的,
更简洁的模板代码可能如下所示:

import csv
with open('stocks.csv') as f:
    f_csv = csv.reader(f) 
    headers = next(f_csv) 
    for row in f_csv:
        # Process row ...

19

通常next(incsv),您会使用它使迭代器前进一排,因此跳过标题。另一个(例如,您想跳过30行)将是:

from itertools import islice
for row in islice(incsv, 30, None):
    # process

6

使用csv.DictReader而不是csv.Reader。如果省略fieldnames参数,则csvfile第一行中的值将用作字段名称。这样便可以使用row [“ 1”]等访问字段值


2

新的“ pandas”软件包可能比“ csv”更相关。下面的代码将读取一个CSV文件,默认情况下将第一行解释为列标题,并在各列中查找最小值。

import pandas as pd

data = pd.read_csv('all16.csv')
data.min()

您也可以将其写成一行:pd.read_csv('all16.csv').min()
FinnÅrupNielsen 2014年

1

好吧,我的迷你包装库也可以完成这项工作。

>>> import pyexcel as pe
>>> data = pe.load('all16.csv', name_columns_by_row=0)
>>> min(data.column[1])

同时,如果您知道什么是标题列索引之一,例如“ Column 1”,则可以执行以下操作:

>>> min(data.column["Column 1"])

1

对我来说,最简单的方法就是使用范围。

import csv

with open('files/filename.csv') as I:
    reader = csv.reader(I)
    fulllist = list(reader)

# Starting with data skipping header
for item in range(1, len(fulllist)): 
    # Print each row using "item" as the index value
    print (fulllist[item])  

1

因为这与我正在做的事情有关,所以我在这里分享。

如果我们不确定是否有标题并且您又不想导入嗅探器和其他内容,该怎么办?

如果您的任务是基本任务,例如打印或追加到列表或数组,则可以使用if语句:

# Let's say there's 4 columns
with open('file.csv') as csvfile:
     csvreader = csv.reader(csvfile)
# read first line
     first_line = next(csvreader)
# My headers were just text. You can use any suitable conditional here
     if len(first_line) == 4:
          array.append(first_line)
# Now we'll just iterate over everything else as usual:
     for row in csvreader:
          array.append(row)

1

Python 3 CSV模块文档提供了以下示例:

with open('example.csv', newline='') as csvfile:
    dialect = csv.Sniffer().sniff(csvfile.read(1024))
    csvfile.seek(0)
    reader = csv.reader(csvfile, dialect)
    # ... process CSV file contents here ...

Sniffer会尝试自动检测有关CSV文件很多东西。您需要显式调用其has_header()方法以确定文件是否具有标题行。如果是这样,则在循环CSV行时跳过第一行。您可以这样做:

if sniffer.has_header():
    for header_row in reader:
        break
for data_row in reader:
    # do something with the row


0

只需添加[1:]

下面的例子:

data = pd.read_csv("/Users/xyz/Desktop/xyxData/xyz.csv", sep=',', header=None)**[1:]**

在iPython中对我有用


0

的Python 3.X

处理UTF8 BOM + HEADER

令人沮丧的是,csv模块无法轻松获取标头,UTF-8 BOM(文件中的第一个字符)也存在一个错误。这仅适用于我的csv模块:

import csv

def read_csv(self, csv_path, delimiter):
    with open(csv_path, newline='', encoding='utf-8') as f:
        # https://bugs.python.org/issue7185
        # Remove UTF8 BOM.
        txt = f.read()[1:]

    # Remove header line.
    header = txt.splitlines()[:1]
    lines = txt.splitlines()[1:]

    # Convert to list.
    csv_rows = list(csv.reader(lines, delimiter=delimiter))

    for row in csv_rows:
        value = row[INDEX_HERE]

0

我将csvreader转换为list,然后弹出第一个元素

import csv        

with open(fileName, 'r') as csvfile:
        csvreader = csv.reader(csvfile)
        data = list(csvreader)               # Convert to list
        data.pop(0)                          # Removes the first row

        for row in data:
            print(row)

0

Python 2.x

csvreader.next()

将读者可迭代对象的下一行作为列表返回,并根据当前方言进行解析。

csv_data = csv.reader(open('sample.csv'))
csv_data.next() # skip first row
for row in csv_data:
    print(row) # should print second row

Python 3.x

csvreader.__next__()

返回读取器的可迭代对象的下一行作为列表(如果该对象是从reader()返回的)或字典(如果它是DictReader实例),则根据当前的方言进行解析。通常,您应该将此称为next(reader)。

csv_data = csv.reader(open('sample.csv'))
csv_data.__next__() # skip first row
for row in csv_data:
    print(row) # should print second row
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.