处理CSV数据时如何忽略第一行数据?
Posted
技术标签:
【中文标题】处理CSV数据时如何忽略第一行数据?【英文标题】:How to ignore the first line of data when processing CSV data? 【发布时间】:2012-07-06 03:40:06 【问题描述】:我要求 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 非常陌生,并希望确保我了解所有内容。
【问题讨论】:
您是否知道您只是在创建一个生成器,它为文件中的每一行返回一个1.0
,然后取最小值,即1.0
?
@Wooble 从技术上讲,它是1.0
的大型生成器。 :)
@Wooble 很好 - ...datatype(row[column]
... 是我猜 OP 试图实现的目标
我有人帮我写了那个代码,但没听懂,所以谢谢哈哈!
【参考方案1】:
您可以使用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)
由于在您的示例中 datatype
和 column
是硬编码的,因此像这样处理 row
会稍微快一些:
data = (float(row[1]) for row in reader)
注意:以上代码适用于 Python 3.x。对于 Python 2.x,使用以下行打开文件,而不是显示的内容:
with open('all16.csv', 'rb') as file:
【讨论】:
代替has_header(file.read(1024))
,写has_header(file.readline())
有意义吗?我看到了很多,但我不明白 has_reader()
是如何检测 CSV 文件的单行中是否有标题...
@Anto:我的答案中的代码基于documentation 中的“Sniffer 使用示例”,所以我认为这是规定的方法。我同意根据一行数据来做这件事似乎并不总是足够的数据来做出这样的决定——但我不知道,因为Sniffer
的工作原理是没有描述。 FWIW 我从未见过 has_header(file.readline())
被使用,即使它在大部分时间都有效,由于上述原因,我会高度怀疑这种方法。
感谢您的意见。尽管如此,似乎使用 file.read(1024)
generates errors in python's csv lib: 。例如,另请参阅here。
@Anto:我从来没有遇到过这样的错误——1024 字节毕竟不是很多内存——根据这个答案的赞成票,这对许多其他人来说也不是问题收到(以及成千上万阅读并遵循文档的人)。由于这些原因,我强烈怀疑是其他原因导致了您的问题。
从readline()
切换到read(1024)
时,我遇到了同样的错误。到目前为止,我只设法找到切换到 readline 来解决 csv.dialect 问题的人。【参考方案2】:
要跳过第一行,只需调用:
next(inf)
Python 中的文件是行上的迭代器。
【讨论】:
Python 文件的精彩总结 你能给一个你找到这个的链接吗?任何指向 next() 文档的链接,其中提到了下一个函数的参数。 @bluetail docs.python.org/3/library/functions.html#next 如果第一行中的一个值可以包含换行符\n
字符,这将不起作用。【参考方案3】:
借自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 ...
【讨论】:
【参考方案4】:在一个类似的用例中,我不得不在带有我实际列名的行之前跳过烦人的行。这个解决方案效果很好。先读取文件,然后将列表传递给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。很高兴在这里学习,您能否提出可以解决您引用的问题的编辑建议?我的解决方案完成了工作,但看起来还可以进一步改进? 我给了你一个编辑,用应该相同的东西(未经测试)替换代码。如果它不符合您的意思,请随时恢复。我仍然不确定您为什么要制作data
字典,这个答案也没有真正比接受的答案添加任何内容。
感谢维德拉克!这看起来确实非常有效。我发布了我的答案,因为接受的答案对我不起作用(现在不记得原因了)。定义 data = dict() 然后立即填充它会有什么问题(与您的建议相比)?
执行data = dict()
并填写它并没有错误,但它效率低且不习惯。另外,即使那样,也应该使用 dict 文字 (
) 和 enumerate
。
FWIW,如果你想确保我收到通知,你应该用 @Veedrac
回复我的帖子,尽管 Stack Overflow 似乎能够从用户名中猜测出来。 (我不写@Maarten
,因为默认会通知回答者。)【参考方案5】:
您通常会使用 next(incsv)
将迭代器前进一排,因此您会跳过标题。另一个(假设你想跳过 30 行)是:
from itertools import islice
for row in islice(incsv, 30, None):
# process
【讨论】:
【参考方案6】:使用 csv.DictReader 代替 csv.Reader。 如果省略 fieldnames 参数,则 csvfile 第一行中的值将用作字段名称。然后,您将能够使用 row["1"] 等访问字段值
【讨论】:
【参考方案7】: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() 或 dict 返回的(如果它是 DictReader instance),根据当前方言解析。通常你应该 将此称为下一个(读者)。
csv_data = csv.reader(open('sample.csv'))
csv_data.__next__() # skip first row
for row in csv_data:
print(row) # should print second row
【讨论】:
【参考方案8】:documentation for the Python 3 CSV module 提供了这个例子:
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
【讨论】:
【参考方案9】:新的“pandas”包可能比“csv”更相关。下面的代码将读取一个 CSV 文件,默认情况下将第一行解释为列标题并找到列之间的最小值。
import pandas as pd
data = pd.read_csv('all16.csv')
data.min()
【讨论】:
你也可以写成一行:pd.read_csv('all16.csv').min()
【参考方案10】:
因为这与我正在做的事情有关,所以我会在这里分享。
如果我们不确定是否有标头并且您也不想导入嗅探器和其他东西怎么办?
如果您的任务是基本的,例如打印或附加到列表或数组,您可以只使用 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)
【讨论】:
【参考方案11】:好吧,我的mini wrapper library 也可以完成这项工作。
>>> import pyexcel as pe
>>> data = pe.load('all16.csv', name_columns_by_row=0)
>>> min(data.column[1])
同时,如果您知道第一个标题列索引是什么,例如“第 1 列”,您可以这样做:
>>> min(data.column["Column 1"])
【讨论】:
【参考方案12】:对我来说,最简单的方法是使用范围。
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])
【讨论】:
【参考方案13】:我会将 csvreader 转换为列表,然后弹出第一个元素
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)
【讨论】:
【参考方案14】:这可能是一个非常古老的问题,但对于 pandas,我们有一个非常简单的解决方案
import pandas as pd
data=pd.read_csv('all16.csv',skiprows=1)
data['column'].min()
skirows=1 我们可以跳过第一行然后我们可以使用 data['column'].min() 找到最小值
【讨论】:
【参考方案15】:我会使用 tail 来去掉不需要的第一行:
tail -n +2 $INFIL | whatever_script.py
【讨论】:
【参考方案16】:只需添加 [1:]
下面的例子:
data = pd.read_csv("/Users/xyz/Desktop/xyxData/xyz.csv", sep=',', header=None)**[1:]**
在 iPython 中对我有用
【讨论】:
【参考方案17】: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]
【讨论】:
【参考方案18】:简单的解决方案是使用 csv.DictReader()
import csv def read_csv(file): with open(file, 'r') as file:
reader = csv.DictReader(file)
for row in reader:
print(row["column_name"]) # Replace the name of column header.
【讨论】:
以上是关于处理CSV数据时如何忽略第一行数据?的主要内容,如果未能解决你的问题,请参考以下文章