Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python CSV中无效行的疑难解答_Python_Pandas_Csv_Sed_Large Data - Fatal编程技术网

Python 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 |

我正在处理一个非常大的CSV文件(接近6GB),它绝对充满了错误。例如,如果我有以下csv文件/表格:

+------------+-------------+------------+
|     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”
    引用(并将其置于
    之间)最后的字母数字字符串,我几乎没有对其进行任何假设(
    [^”]*

  • 这应该会更好地匹配日期(除了始终匹配2月29日,无论年份):


    使用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