坏数据上的 Pandas 数据帧 read_csv

Posted

技术标签:

【中文标题】坏数据上的 Pandas 数据帧 read_csv【英文标题】:Pandas dataframe read_csv on bad data 【发布时间】:2016-01-31 03:55:13 【问题描述】:

我想读取一个非常大的 csv(无法在 excel 中打开并轻松编辑),但在第 100,000 行附近的某处,有一行有一个额外的列导致程序崩溃。这一行出错了,所以我需要一种方法来忽略它是一个额外的列的事实。大约有 50 列,因此对标题进行硬编码并使用名称或 usecols 是不可取的。我也可能会在其他 csv 中遇到这个问题并想要一个通用的解决方案。不幸的是,我在 read_csv 中找不到任何东西。代码就这么简单:

def loadCSV(filePath):
    dataframe = pd.read_csv(filePath, index_col=False, encoding='iso-8859-1', nrows=1000)
    datakeys = dataframe.keys();
    return dataframe, datakeys

【问题讨论】:

除上述之外,使用warn_bad_lines=True 可能会进一步帮助诊断有问题的行。 【参考方案1】:

这是我解决这些问题的方法,它很慢但效果很好, 简单地说,只需将 CSV 文件读取为 txt 文件,然后遍历每一行。 如果“,”逗号小于它应该跳过该行。 最终确保正确的线路安全。

def bad_lines(path):
    import itertools
    num_columns = []
    lines = ""
    
    for i in range(10,50,5):
        content = open(path).readlines(i)[0]
        if (content.count("'") == 0) and (content.count('"') == 0):
            num_columns.append(content.count(","))

    if len(set(num_columns)) == 1:
        for line in itertools.islice(open(path), 0, None):
            if line.count(",") >= num_columns[0]:
                lines = lines + line

    text_file = open("temp.txt", "w")
    n = text_file.write(lines)
    text_file.close()
    
    return("temp.txt")

【讨论】:

有很多更好的方法来处理这个问题,因为你的答案很容易出错。请考虑修改或删除此答案。【参考方案2】:

要获取有关导致错误的行的信息,请尝试使用 error_bad_lines=Falsewarn_bad_lines=True 的组合:

dataframe = pd.read_csv(filePath, index_col=False, encoding='iso-8859-1', nrows=1000,
                        warn_bad_lines=True, error_bad_lines=False)

error_bad_lines=False 跳过导致错误的行,warn_bad_lines=True 打印错误详细信息和行号,如下所示:

'Skipping line 3: expected 4 fields, saw 3401\nSkipping line 4: expected 4 fields, saw 30...'

如果您想保存警告消息(即用于进一步处理),那么您也可以将其保存到文件中(使用contextlib):

import contextlib

with open(r'D:\Temp\log.txt', 'w') as log:
    with contextlib.redirect_stderr(log):
        dataframe = pd.read_csv(filePath, index_col=False, encoding='iso-8859-1', 
                                warn_bad_lines=True, error_bad_lines=False)

【讨论】:

【参考方案3】:

通过error_bad_lines=False 跳过错误的行:

error_bad_lines : 布尔值,默认 True Lines 字段太多 (例如,逗号太多的 csv 行)默认情况下会导致 引发异常,并且不会返回任何 DataFrame。如果为假, 那么这些“坏行”将从 DataFrame 中删除,即 回来。 (仅对 C 解析器有效)

【讨论】:

我忘了提到那个。它适用于我目前想做的事情,但在路上我会想要没有附带额外价值的行。 另一种方法是读取单行以获得正确的列数,然后再次重新读取以仅读取这些列,例如cols = pd.read_csv(file, nrows=1).columns df = pd.read_csv(file, usecols=cols) 然后这将忽略我认为该错误行的附加列尝试并告诉我它是否适合您 @Fonti:truncate_bad_lines 没有选项。这样做将是一个不好的做法。您假设您事先知道数据为什么不好(它附加了一个额外的值)。但是如果它的列太少怎么办?如果插入而不是附加额外的值怎么办?做这样的事情是一个吸虫器。 实际上我刚刚尝试过,但它不起作用,我认为您需要传递 error_bad_lines=False 并解析警告以获取行号并使用 @987654326 读取这些行@ @Edchum 这很奇怪,我认为它对我有用。我没有在该行出现错误,而是出现了内存错误(超过 400 万行)。另一条需要解决的鱼。

以上是关于坏数据上的 Pandas 数据帧 read_csv的主要内容,如果未能解决你的问题,请参考以下文章

如何将 pandas 时间戳添加到数据帧 post read_csv

6.5 GB 文件上的 Pandas read_csv 消耗超过 170 GB RAM

使用分块将 CSV 文件读入 Pandas 数据帧,生成单个目标数据帧

在 pandas 数据帧上并行调用函数

如何将数据读取到 dask 数据帧并删除坏行

将文件从私有 S3 存储桶读取到 pandas 数据帧