Python Pandas:读取具有多个表的csv重复的序言
问题内容:
有没有一种Python方式可以找出CSV文件中的哪些行包含标题和值,哪些行包含垃圾,然后将标题/值行放入数据帧?
我是python的新手,并且一直使用它来读取从科学仪器的数据记录中导出的多个CSV,并且到目前为止,在处理其他任务的CSV时,我始终默认使用该pandas
库。但是,这些CSV导出可能会有所不同,具体取决于每种仪器上记录的“测试”数量。
仪器之间的列标题和数据结构相同,但是有一个“前导”分隔每个可以更改的测试。因此,我得到的备份看起来像这样(在此示例中,有两个测试,但是可能有任意数量的测试):
blah blah here's a test and
here's some information
you don't care about
even a little bit
header1, header2, header3
1, 2, 3
4, 5, 6
oh you have another test
here's some more garbage
that's different than the last one
this should make
life interesting
header1, header2, header3
7, 8, 9
10, 11, 12
13, 14, 15
如果每次我只是使用skiprow参数,它都是固定长度的前同步码,但该前同步码是可变长度的,并且每个测试中的行数是可变长度的。
我的最终目标是能够合并所有测试,并得到如下结果:
header1, header2, header3
1, 2, 3
4, 5, 6
7, 8, 9
10, 11, 12
13, 14, 15
然后我可以像往常一样用大熊猫操纵它。
我已经尝试了以下方法来查找具有预期标题的第一行:
import csv
import pandas as pd
with open('my_file.csv', 'rb') as input_file:
for row_num, row in enumerate(csv.reader(input_file, delimiter=',')):
# The CSV module will return a blank list []
# so added the len(row)>0 so it doesn't error out
# later when searching for a string
if len(row) > 0:
# There's probably a better way to find it, but I just convert
# the list to a string then search for the expected header
if "['header1', 'header2', 'header3']" in str(row):
header_row = row_num
df = pd.read_csv('my_file.csv', skiprows = header_row, header=0)
print df
如果我只有一个测试,则此方法有效,因为它找到了具有标头的第一行,但是当然,header_row
变量每次找到标头时都会进行更新,因此在上面的示例中,我最终输出:
header1 header2 header3
0 7 8 9
1 10 11 12
2 13 14 15
在继续搜索标题/数据集的下一个实例之前,我迷失了如何弄清楚如何将标题/数据集的每个实例附加到数据帧。
而且,当处理大量文件时,必须先通过csv
模块打开一次,然后再使用一次打开,这可能不是超级有效pandas
。
问题答案:
该程序可能会有所帮助。本质上,它是围绕csv.reader()
对象的包装器,该包装器可以收集出良好的数据。
import pandas as pd
import csv
import sys
def ignore_comments(fp, start_fn, end_fn, keep_initial):
state = 'keep' if keep_initial else 'start'
for line in fp:
if state == 'start' and start_fn(line):
state = 'keep'
yield line
elif state == 'keep':
if end_fn(line):
state = 'drop'
else:
yield line
elif state == 'drop':
if start_fn(line):
state = 'keep'
if __name__ == "__main__":
df = open('x.in')
df = csv.reader(df, skipinitialspace=True)
df = ignore_comments(
df,
lambda x: x == ['header1', 'header2', 'header3'],
lambda x: x == [],
False)
df = pd.read_csv(df, engine='python')
print df