相关文章推荐
爱搭讪的大蒜  ·  ADF Parsing JSOn ...·  16 小时前    · 
憨厚的烈酒  ·  JSP在Tomcat的相关配置 ...·  8 月前    · 
绅士的斑马  ·  python ...·  2 年前    · 
近视的墨镜  ·  tableauhyperapi.sqltyp ...·  2 年前    · 

如何用Python只读取CSV文件的标题列?

32 人关注

我正在寻找一种方法,只读取大量大型CSV文件的标题行。

使用Pandas,我有这样的方法,对每个csv文件都有。

>>> df = pd.read_csv(PATH_TO_CSV)
>>> df.columns

I could do this with just the csv module:

>>> reader = csv.DictReader(open(PATH_TO_CSV))
>>> reader.fieldnames

这些文件的问题是,每个CSV文件的大小都在500MB以上,如果只是为了提取标题行而读取每个文件的全部内容,似乎是一种巨大的浪费。

我做这一切的最终目的是为了拉出独特的列名。一旦我有了这些文件中的列头列表,我就可以做到这一点。

如何快速地只提取CSV文件的标题行?

1 个评论
请注意, DictReader 并不读取整个文件......所以你可以在需要的文件上反复使用,并建立一个集合......我在我做的一个回答中也做了类似的事情...
python
csv
pandas
Andy
Andy
发布于 2014-07-26
10 个回答
Jarno
Jarno
发布于 2019-03-23
已采纳
0 人赞同

在此基础上扩展 杰夫的回答 现在可以使用 pandas 而不实际读取任何行。

In [1]: import pandas as pd
In [2]: import numpy as np
In [3]: pd.DataFrame(np.random.randn(10, 4), columns=list('abcd')).to_csv('test.csv', mode='w')
In [4]: pd.read_csv('test.csv', index_col=0, nrows=0).columns.tolist()
Out[4]: ['a', 'b', 'c', 'd']

替换代码0】的好处是它能更优雅地处理CSV编码。

你好,很好的提示。 我发现将 index_col 替换为 header 得到了我所缺少的一个额外的字段名。 除此以外,其余部分都工作得很好!
@MarkMoretto 我认为这取决于你的CSV中是否有一个没有标题的额外索引列。如果没有,那么设置 index_col=False 可能是最清楚的,因为 header=0 已经是一种默认值了。
Tyler
Tyler
发布于 2019-03-23
0 人赞同

我可能有点晚了,但这里有一种方法,只用Python标准库就可以做到。当处理文本数据时,我更喜欢使用Python 3,因为unicode。所以这和你原来的建议非常接近,只是我只读入一行而不是整个文件。

import csv    
with open(fpath, 'r') as infile:
    reader = csv.DictReader(infile)
    fieldnames = reader.fieldnames

希望这能有所帮助!

这应该是新的公认答案。这是最快速和最清晰的方法
Jon Clements
Jon Clements
发布于 2019-03-23
0 人赞同

我以 iglob 为例来搜索 .csv 的文件,但有一种方法是使用一个集合,然后根据需要进行调整,例如。

import csv
from glob import iglob
unique_headers = set()
for filename in iglob('*.csv'):
    with open(filename, 'rb') as fin:
        csvin = csv.reader(fin)
        unique_headers.update(next(csvin, []))
    
Andy
我把这个和杰夫提供的答案进行了比较。对于我的数据集的一个样本,这个答案比pandas的答案快5倍左右。我怀疑这是因为它没有读取额外的数据行(我也很感谢关于DictReader的说明)。谢谢
@Andy 我怀疑真正的区别并不是不必要地读取额外的行,而是创建一个DataFrame来做这件事的开销。
我想知道这句话是什么意思?"unique_headers.update(next(csvin, []))"@JonClements
Jeff
Jeff
发布于 2019-03-23
0 人赞同

这里有一个方法。你得到1行。

In [9]: DataFrame(np.random.randn(10,4),columns=list('abcd')).to_csv('test.csv',mode='w')
In [10]: read_csv('test.csv',index_col=0,nrows=1)
Out[10]: 
          a         b         c         d
0  0.365453  0.633631 -1.917368 -1.996505
    
虽然为了阅读标题,这确实读出了一个不必要的行......但也许我并不完全清楚OP的愿望。
Andy
我感谢你的回答,杰夫。我把你的答案和乔恩提供的答案进行了比较。两者都能工作,但这个答案的运行速度比他提供的那个慢5倍。
@Jon Clements OP只需要头文件,但 read_csv() 不与 nrows=0 一起运行。- read_csv() 需要至少读取一行。
Jeff
@Andy 如果这对你来说很重要,那就用另一个解决方案吧。这是pandas的方法。
@Jeff & Jon Clements: I think you could add header=None to get headers as normal row - without first row of data.
mdubez
mdubez
发布于 2019-03-23
0 人赞同
pandas.read_csv(PATH_TO_CSV, nrows=1).columns

这将只读取第一行并返回找到的列。

仍然创建一个不必要的第一行的数据框架
Saurabh Chandra Patel
Saurabh Chandra Patel
发布于 2019-03-23
0 人赞同

你漏掉了 nrows=1 的参数read_csv

>>> df= pd.read_csv(PATH_TO_CSV, nrows=1)
>>> df.columns
    
Muhieddine Alkousy
Muhieddine Alkousy
发布于 2019-03-23
0 人赞同

这取决于页眉的用途,如果你只需要页眉用于比较(我的例子),这段代码将很简单而且超级快,它将把整个页眉读成一个字符串。你可以根据你的需要把所有收集的字符串转换到一起。

for filename in glob.glob(files_path+"\*.csv"):
    with open(filename) as f:
        first_line = f.readline()
    
Sway Wu
Sway Wu
发布于 2019-03-23
0 人赞同

这很容易,你可以使用这个。

df = pd.read_csv("path.csv", skiprows=0, nrows=2)
df.columns.to_list()

在这种情况下,你只能读取真正的几行来获得你的标题

blessedk
blessedk
发布于 2019-03-23
0 人赞同

如果你只对标题感兴趣,并且想使用pandas,那么除了csv文件名之外,你唯一需要传递的额外东西就是 "nrows=0"。

headers = pd.read_csv("test.csv", nrows=0)
    
Aaksh Kumar
Aaksh Kumar
发布于 2019-03-23
0 人赞同