对于坏数据,Pandas dataframe read_csv

时间:2015-10-30 16:36:17

标签: python csv pandas

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

3 个答案:

答案 0 :(得分:65)

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

  

error_bad_lines:boolean,default True包含太多字段的行   (例如,逗号太多的csv行)默认会导致   要引发的异常,并且不会返回任何DataFrame。如果为假,   然后这些“坏线”将从DataFrame中删除   回。 (仅对C解析器有效)

答案 1 :(得分:5)

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

答案 2 :(得分:0)

这是我解决这些问题的方法,虽然速度很慢但效果很好, 简单地说,只需将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")