Python:在csv.DictReader中跳过标有#的注释行

Dan*_*ell 63 python csv comments

使用csv.DictReader处理CSV文件非常棒 - 但是我有带有注释行的CSV文件(在行的开头用哈希表示),例如:

# step size=1.61853
val0,val1,val2,hybridisation,temp,smattr
0.206895,0.797923,0.202077,0.631199,0.368801,0.311052,0.688948,0.597237,0.402763
-169.32,1,1.61853,2.04069e-92,1,0.000906546,0.999093,0.241356,0.758644,0.202382
# adaptation finished

csv模块不包含任何跳过此类行的方法.

我可以很容易地做一些hacky,但我想有一种很好的方法可以将csv.DicReader包装在一些其他迭代器对象周围,该对象预处理以丢弃这些行.

Dan*_*ell 82

实际上这适用于filter:

import csv
fp = open('samples.csv')
rdr = csv.DictReader(filter(lambda row: row[0]!='#', fp))
for row in rdr:
    print(row)
fp.close()
Run Code Online (Sandbox Code Playgroud)

  • ...或生成器表达式:`csv.DictReader(如果不是row.startswith('#'),则为fp中的行的行) (36认同)
  • 这将把整个文件读入内存.如果它不是太大那么没问题,否则你可能想要使用生成器表达式或`itertools.ifilter()`. (18认同)
  • @Duncan不需要Python3.6中的itertools,因为`filter()`默认会返回一个迭代器,因此该文件不会被加载到内存中. (5认同)

Gra*_*ing 10

另一种读取 CSV 文件的方法是使用 pandas

这是一个示例代码:

df = pd.read_csv('test.csv',
                 sep=',',     # field separator
                 comment='#', # comment
                 index_col=0, # number or label of index column
                 skipinitialspace=True,
                 skip_blank_lines=True,
                 error_bad_lines=False,
                 warn_bad_lines=True
                 ).sort_index()
print(df)
df.fillna('no value', inplace=True) # replace NaN with 'no value'
print(df)
Run Code Online (Sandbox Code Playgroud)

对于这个 csv 文件:

a,b,c,d,e
1,,16,,55#,,65##77
8,77,77,,16#86,18#
#This is a comment
13,19,25,28,82
Run Code Online (Sandbox Code Playgroud)

我们将得到这个输出:

       b   c     d   e
a                     
1    NaN  16   NaN  55
8   77.0  77   NaN  16
13  19.0  25  28.0  82
           b   c         d   e
a                             
1   no value  16  no value  55
8         77  77  no value  16
13        19  25        28  82
Run Code Online (Sandbox Code Playgroud)

  • 问题的作者可能不需要熊猫。但是这个论坛的目的不仅仅是帮助每个问题的作者解决他们的具体问题。 (6认同)
  • `pandas` 确实是一个强大的库,但它是一个需要设置和学习使用的依赖项。而且,作者在问题中已经说过,他只是想使用内置的“csv.DictReader”模块,并且几年前就已经提供了相关答案。我不明白您为什么添加此解决方案作为替代方案。 (2认同)

sig*_*ldm 8

一个很好的问题,一个很好的例子,说明Python的CSV库如何缺少重要的功能,例如处理基本注释(在CSV文件顶部并不罕见)。虽然Dan Stowell的解决方案适用于OP的特定情况,但它的局限性在于#必须以第一个符号出现。更通用的解决方案是:

def decomment(csvfile):
    for row in csvfile:
        raw = row.split('#')[0].strip()
        if raw: yield raw

with open('dummy.csv') as csvfile:
    reader = csv.reader(decomment(csvfile))
    for row in reader:
        print(row)
Run Code Online (Sandbox Code Playgroud)

例如,以下dummy.csv文件:

# comment
 # comment
a,b,c # comment
1,2,3
10,20,30
# comment
Run Code Online (Sandbox Code Playgroud)

退货

['a', 'b', 'c']
['1', '2', '3']
['10', '20', '30']
Run Code Online (Sandbox Code Playgroud)

当然,与一样好用csv.DictReader()

  • 我相信您的意思是 decomment() 函数中的“yield row”而不是“yield raw”。CSV 文件可以在字符串中包含 # 个字符,并且它完全有效。 (3认同)
  • @ThibaultReuille:确实,许多 CSV 文件可以在字符串中包含 #,尽管 CSV 格式没有很好地标准化。我的意思是“原始产量”。我的建议在任何情况下都不会处理字符串中的#。 (2认同)