使用 Pandas 将 CSV 读入具有不同行长的数据帧
Posted
技术标签:
【中文标题】使用 Pandas 将 CSV 读入具有不同行长的数据帧【英文标题】:Read CSV into a dataFrame with varying row lengths using Pandas 【发布时间】:2019-08-03 09:46:12 【问题描述】:所以我有一个看起来有点像这样的 CSV:
1 | 01-01-2019 | 724
2 | 01-01-2019 | 233 | 436
3 | 01-01-2019 | 345
4 | 01-01-2019 | 803 | 933 | 943 | 923 | 954
5 | 01-01-2019 | 454
...
当我尝试使用以下代码生成数据帧时..
df = pd.read_csv('data.csv', header=0, engine='c', error_bad_lines=False)
它只将 3 列的行添加到 df(上面的第 1、3 和 5 行)
其余的被认为是“坏行”,给我以下错误:
Skipping line 17467: expected 3 fields, saw 9
如何在我的 csv 中创建一个包含 所有 数据的数据框,可能只是用 null 填充空单元格?还是我必须在添加到 df 之前声明最大行长度?
谢谢!
【问题讨论】:
您将需要低于最大长度的行才能有空列,因此在普通的csv
中类似于a,b,c,,,,
【参考方案1】:
如果您知道数据包含N
列,您可以
通过names
参数提前告诉 Pandas 需要多少列:
import pandas as pd
df = pd.read_csv('data', delimiter='|', names=list(range(7)))
print(df)
产量
0 1 2 3 4 5 6
0 1 01-01-2019 724 NaN NaN NaN NaN
1 2 01-01-2019 233 436.0 NaN NaN NaN
2 3 01-01-2019 345 NaN NaN NaN NaN
3 4 01-01-2019 803 933.0 943.0 923.0 954.0
4 5 01-01-2019 454 NaN NaN NaN NaN
如果您对列数有上限N
,那么您可以
让 Pandas 读取 N
列,然后使用 dropna
删除完全空的列:
import pandas as pd
df = pd.read_csv('data', delimiter='|', names=list(range(20))).dropna(axis='columns', how='all')
print(df)
产量
0 1 2 3 4 5 6
0 1 01-01-2019 724 NaN NaN NaN NaN
1 2 01-01-2019 233 436.0 NaN NaN NaN
2 3 01-01-2019 345 NaN NaN NaN NaN
3 4 01-01-2019 803 933.0 943.0 923.0 954.0
4 5 01-01-2019 454 NaN NaN NaN NaN
请注意,这可能会从数据集的中间删除列(不仅仅是 右侧的列)如果它们完全为空。
【讨论】:
由于某种原因,其他解决方案对我不起作用,但添加names
参数就可以了,干杯!
添加名称对我有用,因为我在大型 csv 中有不规则的列。谢谢!【参考方案2】:
colnames= [str(i) for i in range(9)]
df = pd.read_table('data.csv', header=None, sep=',', names=colnames)
如果代码出现错误,请将列名中的 9
更改为数字 x
Skipping line 17467: expected 3 fields, saw x
【讨论】:
【参考方案3】:考虑使用 Python csv
来完成导入数据和格式修饰的提升。您可以实现自定义方言来处理不同的 csv-ness。
import csv
import pandas as pd
csv_data = """1 | 01-01-2019 | 724
2 | 01-01-2019 | 233 | 436
3 | 01-01-2019 | 345
4 | 01-01-2019 | 803 | 933 | 943 | 923 | 954
5 | 01-01-2019 | 454"""
with open('test1.csv', 'w') as f:
f.write(csv_data)
csv.register_dialect('PipeDialect', delimiter='|')
with open('test1.csv') as csvfile:
data = [row for row in csv.reader(csvfile, 'PipeDialect')]
df = pd.DataFrame(data = data)
为您提供 csv 导入方言和以下 DataFrame:
0 1 2 3 4 5 6
0 1 01-01-2019 724 None None None None
1 2 01-01-2019 233 436 None None None
2 3 01-01-2019 345 None None None None
3 4 01-01-2019 803 933 943 923 954
4 5 01-01-2019 454 None None None None
剩下的练习是处理输入文件中的空白填充。
【讨论】:
自我说明:pandas.read_csv(engine=) 将使用 python 的 csv 模块(如果指定)。【参考方案4】:读取固定宽度应该可以工作:
from io import StringIO
s = '''1 01-01-2019 724
2 01-01-2019 233 436
3 01-01-2019 345
4 01-01-2019 803 933 943 923 954
5 01-01-2019 454'''
pd.read_fwf(StringIO(s), header=None)
0 1 2 3 4 5 6
0 1 01-01-2019 724 NaN NaN NaN NaN
1 2 01-01-2019 233 436.0 NaN NaN NaN
2 3 01-01-2019 345 NaN NaN NaN NaN
3 4 01-01-2019 803 933.0 943.0 923.0 954.0
4 5 01-01-2019 454 NaN NaN NaN NaN
或使用delimiter
参数
s = '''1 | 01-01-2019 | 724
2 | 01-01-2019 | 233 | 436
3 | 01-01-2019 | 345
4 | 01-01-2019 | 803 | 933 | 943 | 923 | 954
5 | 01-01-2019 | 454'''
pd.read_fwf(StringIO(s), header=None, delimiter='|')
0 1 2 3 4 5 6
0 1 01-01-2019 724 NaN NaN NaN NaN
1 2 01-01-2019 233 436.0 NaN NaN NaN
2 3 01-01-2019 345 NaN NaN NaN NaN
3 4 01-01-2019 803 933.0 943.0 923.0 954.0
4 5 01-01-2019 454 NaN NaN NaN NaN
请注意,对于您的实际文件,您不会使用StringIO
,您只需将其替换为您的文件路径:pd.read_fwf('data.csv', delimiter='|', header=None)
【讨论】:
【参考方案5】:在 csv 文件的顶部添加额外的列(空的或其他的)。 Pandas 将第一行作为默认大小,低于它的任何内容都将具有 NaN 值。示例:
文件.csv:
a,b,c,d,e
1,2,3
3
2,3,4
代码:
>>> import pandas as pd
>>> pd.read_csv('file.csv')
a b c d e
0 1 2.0 3.0 NaN NaN
1 3 NaN NaN NaN NaN
2 2 3.0 4.0 NaN NaN
【讨论】:
【参考方案6】:如果只使用pandas
,读入行,处理后面的分隔符。
import pandas as pd
df = pd.read_csv('data.csv', header=None, sep='\n')
df = df[0].str.split('\s\|\s', expand=True)
0 1 2 3 4 5 6
0 1 01-01-2019 724 None None None None
1 2 01-01-2019 233 436 None None None
2 3 01-01-2019 345 None None None None
3 4 01-01-2019 803 933 943 923 954
4 5 01-01-2019 454 None None None None
【讨论】:
非常紧凑!是否有一种简单的方法来处理包含分隔符的文本行?我认为逗号作为分隔符和包含逗号的文本,或者在 OP 的情况下类似于2 | 01-01-2019 | "Two | | lines" | 123 | text
以上是关于使用 Pandas 将 CSV 读入具有不同行长的数据帧的主要内容,如果未能解决你的问题,请参考以下文章
使用分块将 CSV 文件读入 Pandas 数据帧,生成单个目标数据帧