Python CSV中无效行的疑难解答
我正在处理一个非常大的CSV文件(接近6GB),它绝对充满了错误。例如,如果我有以下csv文件/表格:Python CSV中无效行的疑难解答,python,pandas,csv,sed,large-data,Python,Pandas,Csv,Sed,Large Data,我正在处理一个非常大的CSV文件(接近6GB),它绝对充满了错误。例如,如果我有以下csv文件/表格: +------------+-------------+------------+ | ID | Date | String | +------------+-------------+------------+ | 123456 | 09-20-2019 | ABCDEFG | | 123abc456 | 10-30-2019 |
+------------+-------------+------------+
| ID | Date | String |
+------------+-------------+------------+
| 123456 | 09-20-2019 | ABCDEFG |
| 123abc456 | 10-30-2019 | HIJKLMN |
| 7891011 | jdqhouehwf | OPQRSTU |
| 1010101 | 03-15-2018 | 8473737 |
| 4823.00 | 02-11-2015 | VWXYZ |
| 2348813.0 | 01-23-2016 | BAZ |
+------------+-------------+------------+
或:
我想要一个解决问题和修复文件的好方法。使用熊猫,我可以在文件中读取:
import pandas as pd
df = pd.read_csv(inputfile)
熊猫总是会抱怨如下:
sys:1:DtypeWarning:列(0)具有混合类型。在导入时指定数据类型选项或设置低内存=False
所以我想清理每一列。但由于它是一个非常大的文件,我不能只打印我的整个表,以屏蔽输出,并期望读取它。我想要一个简单的方法来获取一个列并检查它是否符合类型。此外,如果可能的话,我还需要一种删除坏行和/或将行转换为正确格式的方法。说到底,我希望文件看起来像(不包括内联注释):
正如您标记的
sed
,这里有一个命令应该以一种非常高效和可移植的方式完成这项工作,但它有点不可读
sed -n '1p;s/^"\{0,1\}\([0-9]\+\)\(\.[0-9]*\)\{0,1\}"\{0,1\}\(,"\(0[0-9]\|1[0-2]\)-\([0-2][0-9]\|3[01]\)-2[0-9]\{3\}",\)"\{0,1\}\([^"]*\)"\{0,1\}$/\1\3"\6"/p' file
它所做的是:
1p
)s
)命令,仅当替换成功时(因此仅当该行与搜索模式匹配时)才打印结果\1\3“\6”
,每个转义数字都指向相应的编码捕获组(\(…\)
;请记住,根据开头\(
标记出现的顺序为这些组分配了一个数字。具体来说:
\1
指的是前导号码([0-9]\+
),有或没有(\{0,1\}
)以下三项:
- 前导的
“
- 尾随的小数部分
\.[0-9]*
- 以及下面的
“
\3
指的是包含的日期(“
”\(0[0-9]\\124; 1[0-2]\)-\([0-2][0-9]\\124; 3[01]\)-2[0-9]\{3\}”,注意我在这个正则表达式中不准确,因为它也会匹配不存在的日期,如2月31日)“\6”
引用(并将其置于“
之间)最后的字母数字字符串,我几乎没有对其进行任何假设([^”]*
)使用csv模块逐行对其进行预处理,并将更正的/有效的行/行写入新文件。这对于剔除错误条目非常有用,但如果可能,它不会处理转换。理想情况下,删除一行只能作为最后的手段。@Geoffreysans,转换什么?csv文件是文本文件,不是吗?在您对c的评论中ode在我看来,您使用convert to int来表示删除
“
和小数部分。
"ID","Date","String"
123456,"09-20-2019","ABCDEFG"
# 123abc456,"10-30-2019","HIJKLMN" was deleted because the ID wasn't a number
# 7891011,"jdqhouehwf","OPQRSTU" was deleted because the data was not a date
1010101,"03-15-2018","8473737" # The last number could be converted to string
4823,"02-11-2015","VWXYZ" # The first number could be converted to integer
2348813,"01-23-2016","BAZ" # The ID number could be converted to int
def main():
from pathlib import Path
import csv
import datetime as dt
with Path("thing.csv").open("r") as file:
for row in csv.DictReader(file):
try:
row["ID"] = int(float(row["ID"]))
row["Date"] = dt.datetime.strptime(row["Date"], "%m-%d-%Y")
except (KeyError, ValueError):
continue
print(*row.values())
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
sed -n '1p;s/^"\{0,1\}\([0-9]\+\)\(\.[0-9]*\)\{0,1\}"\{0,1\}\(,"\(0[0-9]\|1[0-2]\)-\([0-2][0-9]\|3[01]\)-2[0-9]\{3\}",\)"\{0,1\}\([^"]*\)"\{0,1\}$/\1\3"\6"/p' file
sed -n '1p;s/^"\{0,1\}\([0-9]\+\)\(\.[0-9]*\)\{0,1\}"\{0,1\}\(,"\(\(0[0-9]\|1[0-2]\)-[0-2][0-9]\|\(0[469]\|11\)-30\|\(0[13578]\|1[02]\)-31\)-2[0-9]\{3\}",\)"\{0,1\}\([^"]*\)"\{0,1\}$/\1\3"\8"/p' file