如何使用csv.DictReader跳过前标题行?

ybzsozfc  于 2023-11-14  发布在  其他
关注(0)|答案(3)|浏览(114)

我想csv.DictReader从文件中推导出字段名。文档说 “如果省略了fieldnames参数,则csv文件的第一行中的值将用作字段名。",但在我的情况下,第一行包含标题,第二行包含名称。
我不能像Python 3.2 skip a line in csv.DictReader那样应用next(reader),因为字段名赋值是在初始化读取器时发生的(或者我做错了)。
csv文件(从Excel 2010导出,original source):

CanVec v1.1.0,,,,,,,,,^M
Entity,Attributes combination,"Specification Code
Point","Specification Code
Line","Specification Code
Area",Generic Code,Theme,"GML - Entity name
Shape - File name
Point","GML - Entity name
Shape - File name
Line","GML - Entity name
Shape - File name
Area"^M
Amusement park,Amusement park,,,2260012,2260009,LX,,,LX_2260009_2^M
Auto wrecker,Auto wrecker,,,2360012,2360009,IC,,,IC_2360009_2^M

字符串
我的代码:

f = open(entities_table,'rb')
try:
    dialect = csv.Sniffer().sniff(f.read(1024))
    f.seek(0)

    reader = csv.DictReader(f, dialect=dialect)
    print 'I think the field names are:\n%s\n' % (reader.fieldnames)

    i = 0
    for row in reader:
        if i < 20:
            print row
            i = i + 1

finally:
    f.close()


目前的成果:

I think the field names are:
['CanVec v1.1.0', '', '', '', '', '', '', '', '', '']


预期结果:

I think the field names are:
['Entity','Attributes combination','"Specification Code Point"',...snip]


我意识到,删除第一行并继续执行操作是一种权宜之计,但我正试图尽可能地接近原位阅读数据,并尽量减少手动干预。

zkure5ic

zkure5ic1#

f.seek(0)之后插入:

next(f)

字符串
在初始化DictReader之前将文件指针前进到第二行。

m1m5dgzv

m1m5dgzv2#

我使用了itertools的islice。我的header位于一个大的preamble的最后一行。我已经传递了preamble并使用hederline作为字段名:

with open(file, "r") as f:
    '''Pass preamble'''
    n = 0
    for line in f.readlines():
        n += 1
        if 'same_field_name' in line: # line with field names was found
            h = line.split(',')
            break
    f.close()
    f = islice(open(i, "r"), n, None)

    reader = csv.DictReader(f, fieldnames = h)

字符串

myss37ts

myss37ts3#

通用解决方案

这是一个更通用的解决方案,当它不确定标题将到达哪一行时。
这个解决方案还清理了标题-期望第一个“单词”(空格分隔)作为实际的列标题,尾部字符被视为注解(并被删除)。

无法完全在csv.DictReader中实现

csv.DictReader中无法处理跳过行。首先,它没有“跳过行数”功能(如Pandas),而且,我们不知道它会有多少行。因此确定需要外部处理。文件内容需要读取和处理。

清洁解决方案

欢迎提出改进建议,但此解决方案避免了导入不必要的库,并且不使用像closing a file within a context manager and re-opening it(!)这样的漏洞。

Python 3

import csv

FILENAME = "data.csv"

with open(FILENAME, newline="", encoding="utf-8") as csvfile:
    for line in csvfile:
        if "known_field_name" in line:
            break
    else:
        sys.exit("Error: Headers not found")
    fieldnames = [(field.strip().split() or [""])[0] for field in line.split(",")]
    rows = [row for row in csv.DictReader(csvfile, fieldnames=fieldnames)]

print("Field names are: {}".format(fieldnames)) 

for row in rows:
    print(row)

字符串
请注意,这段代码不会产生问题中预期的结果,因为列标题在测试数据中包含空格,并且此解决方案具有清除列标题的特定功能。
如果列标题中允许空格,则删除该功能。

Slurping整个文件

这个解决方案会slurps整个文件,以便尽早丢弃文件句柄,因为它适用于较小的数据集。如果正在使用大数据集,则在csvfile上下文管理器中继续处理,不要将整个文件slurps到初始列表中。

字段名处理

(field.strip().split() or [""])[0]步骤用于获取干净的列标题。因为field.strip()可以生成空字符串,那么field.strip().split()也可以生成空列表,然后[][0]将引发异常。
这是... or [""]确保有一个长度为1或更大的列表,以避免提高IndexError
为第一个项目编制索引是必要的,以便将列标题单元格中的第一个单词与其他注解分开(不允许使用换行符或逗号,请参见下文)。

漏洞

字段名处理必须手动完成,在csv之外。特别是,逗号分割的简单方法预计将从一行提供所有列标题。

  • 列标题中不允许使用逗号
  • 不允许在列标题内换行

如果这两个规则中的一个或两个都被打破,则该代码将不会“实现”,并且处理将中断。

相关问题