处理具有多个独立标题的CSV文件
我刚开始学习Python(还有Stack Overflow这个网站),现在想处理一个CSV文件,这个文件分成两个部分,每个部分都有自己的表头,而且长度不同。
第一部分只有两行:一行是有13列的表头,第二行是数据。
在两行空行之后,第二部分开始了,先是一个表头,这次有42个条目,后面跟着不定数量的数据行。
看看这个(简化过的)例子:
A | B | C | D | E | F | G | H | |
---|---|---|---|---|---|---|---|---|
1 | 文件名 | 日期 | 时间 | 编号 | 类型 | |||
2 | report.csv | 2024年3月27日 | 11:15 | 12345 | 东西 | |||
3 | ||||||||
4 | ||||||||
5 | 编号 | 设备 | 版本 | 读数日期 | 读数时间 | 值1 | 值2 | 值3 |
6 | 1 | 2345678 | 10 | 2024年3月26日 | 10:00 | 463 | 470 | 482 |
7 | 2 | 3456789 | 11 | 2024年3月26日 | 11:00 | 298 | 340 | 363 |
8 | 3 | 4567890 | 12 | 2024年3月26日 | 12:00 | 587 | 600 | 621 |
9 | ... |
我想做的是把这两个部分当作两个独立的东西来处理,并为每个部分创建一个字典,最好不需要创建任何“辅助”文件(比如把它分成两个单独的CSV文件)。到目前为止,我尝试了很多方法,比如用csv.DictReader
,pandas.read_csv
配合设置chunksize
或者给header
参数传递一系列行索引。但我在网上搜索了一个小时,还是找不到有类似问题的人。
4 个回答
使用标准的csv库(不是pandas),你可以通过在for循环中使用'next'命令来跳过你需要的任意数量的表头行。下面的代码展示了如何打开一个文件并跳过你需要的行数(在这个例子中是跳过5行)
import csv
reader = csv.reader(open('test.csv'), delimiter=';')
for row in range(5):
next(reader) # skip header line
# start displaying for the 6th row
for row in reader:
print(row)
如果表头的行数不固定,你可以在读取文件时循环检查,找到包含你数据实际表头的那一行。你可以通过检查第一列的值来寻找表头的名称:
import csv
reader = csv.reader(open('test.csv'), delimiter=';')
for row in reader:
# check the row is not empty and check for 1st column (row[0])
if row !=[] and row[0] == 'first_col_header':
print (row)
python 3.11.5 pandas 2.2.1
我们可以用 csv.reader
来按顺序加载数据。
假设我们有一个csv文件,里面的数据是这样的:
import csv, io
raw_data = '''File name,Date,Time,ID,Type
report.csv,27.03.2024,11:15,12345,Thing
No.,Device,Version,Readout date,Readout time,Value 1,Value 2,Value 3
1,2345678,10,26.03.2024,10:00,463,470,482
2,3456789,11,26.03.2024,11:00,298,340,363
3,4567890,12,26.03.2024,12:00,587,600,621
'''
data = csv.reader(io.StringIO(raw_data))
我们可以通过读取前两行直接创建第一个字典:
first_table = dict(zip(next(data), next(data)))
要获取下一个字典,我们可以使用 pandas.DataFrame
,但首先得跳过空行:
import pandas as pd
for line in data:
if line:
break
df = pd.DataFrame(data, columns=line)
或者,为了更保险一点:
for line in data:
if any(cell.strip() for cell in line):
break
else:
raise(ValueError('No data for the second table found'))
df = pd.DataFrame(data, columns=line)
如果不能使用Pandas,我们可以像之前那样,通过将表头和其他数据配对来创建一个字典:
for headers in data:
if any(cell.strip() for cell in headers):
break
columns = zip(*data)
second_table = dict(zip(headers, columns))
可以尝试的代码:
from csv import reader
from itertools import takewhile
data = reader(open('data.csv'))
tables = []
for record in data:
if record:
headers = record
rows = takewhile(bool, data)
columns = map(list, zip(*rows))
tables.append(dict(zip(headers, columns)))
你可以很简单地用 .iloc 函数来分割这个 CSV 文件。首先,你需要把 CSV 文件读成一个数据框(dataframe):
import pandas as pd
my_csv = pd.read_csv('my_csv.csv')
接下来,创建两个变量,用来定义数据框的不同部分,作为新的数据框,比如:
df1 = my_csv[:3]
df2 = my_csv[5:]
如果列名没有正确读取,你需要单独给列命名,比如:
df1.columns = ['No. Device', 'Version', 'Readout date', 'Readout time', 'Value 1', 'Value 2', 'Value 3']
希望这些对你有帮助