熊猫数据框read_csv上的不良数据


76

我想读取一个非常大的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

2
除上述内容外,使用warn_bad_lines=True可能还有助于诊断有问题的行。
疱疹免费工程师

Answers:


109

传递error_bad_lines=False以跳过错误的行:

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


我忘了提到那个。它将适合我当前想要做的事情,但是一路走来,我将希望该行没有附带的额外价值。
Fonti 2015年

9
另一种方法是读取一行以获取正确的cols数,然后再次重新读取以仅读取那些列,例如,cols = pd.read_csv(file, nrows=1).columns df = pd.read_csv(file, usecols=cols)这将忽略我认为该错误行的其他列,然后尝试尝试并让我知道它是否适用您
EdChum

2
@Fonti:没有选择truncate_bad_lines。这样做将是一个坏习惯。您假设您事先知道数据为什么不好(数据附加了额外的值)。但是,如果列数太少怎么办?如果插入了附加值而不是附加了该怎么办?做这样的事情会吸引人。
Steven Rumbalski 2015年

2
实际上,我只是尝试了一下,但它行不通,我认为您需要通过error_bad_lines=False并解析警告以获取行号,并使用header=None
EdChum 2015年

@Edchum奇怪,我认为它对我有用。我没有在那一行出现错误,而是遇到了内存错误(400万行以上)。一整条鱼都可以解决。
Fonti

9

要获取有关导致行出错的信息,请尝试使用error_bad_lines=False和的组合warn_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)

-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")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.