Pandas对错误数据执行 Dataframe read_csv

dldeef67  于 2022-12-06  发布在  其他
关注(0)|答案(5)|浏览(298)

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

k4ymrczo1#

传递error_bad_lines=False以跳过错误行:
错误行:boolean,默认值True默认情况下,包含太多字段的行(例如,包含太多逗号的csv行)将引发异常,并且不会返回任何DataFrame。如果为False,则将从返回的DataFrame中删除这些“错误行”。(仅对C解析器有效)

n8ghc7c1

n8ghc7c12#

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

pxyaymoc3#

对于任何像我这样在最初发布的几年后才遇到这个问题的人来说,其他的答案建议使用error_bad_lines=Falsewarn_bad_lines=True,但这两个都在Pandas中被否决了。
相反,使用on_bad_lines = 'warn'来实现跳过坏数据线的相同效果。

dataframe = pd.read_csv(filePath, index_col=False, encoding='iso-8859-1', nrows=1000, on_bad_lines = 'warn')

on_bad_lines = 'warn'将在遇到坏行时发出警告并跳过该行。
对于on_bad_linesOther acceptable values

  • “error”,它在错误行上引发异常
  • “skip”将跳过任何错误行
zf9nrax1

zf9nrax14#

1.4.0版新增功能

pandas1.4.0开始,read_csv()通过允许将可调用对象分配给on_bad_lines=,提供了允许您以更优雅和智能的方式处理这些情况的功能。
例如,假设CSV可能导致错误数据:Expected 4 fields in line 3, saw 5

C1,C2,C3,C4
10,11,12,13
25,26,27,28,garbage
80,81,82,83

下面的lambda函数简单地忽略了错误行中的最后一列(正如上面的原始问题语句所期望的):

df = pd.read_csv('your.csv', on_bad_lines=lambda x: x[:-1], engine='python')
df

   C1  C2  C3  C4
0  10  11  12  13
1  25  26  27  28
2  80  81  82  83

on_bad_lines可调用函数在每个错误行上调用,并具有函数签名(bad_line: list[str]) -> list[str] | None。如果函数返回None,则错误行将被忽略。如您所见,engine='python'是必需的。
这一点的好处是,它为您编写任何细粒度逻辑来解决问题打开了大门。
例如,假设您要删除行首或行尾的错误数据,如果行首和行尾都有错误数据,则忽略该行,您可以:

CSV格式

C1,C2,C3,C4
10,11,12,13
20,21,22,23,garbage
60,61,62,63
trash,80,81,82,83
trash,90,91,82,garbage

函数定义

def line_fixer(x):
    if not x[0].isnumeric() and x[-1].isnumeric():
        return x[1:] 
    
    if not x[-1].isnumeric() and x[0].isnumeric():
        return x[:-1]
    
    return None

结果

df = pd.read_csv('your.csv', on_bad_lines=line_fixer, engine='python')
df

   C1  C2  C3  C4
0  10  11  12  13
1  20  21  22  23
2  60  61  62  63
3  80  81  82  83
nfg76nw0

nfg76nw05#

这里是我的方法来解决这些问题,它是缓慢的,但工作得很好,简单地说,只是读取CSV文件作为txt文件,并通过每一行.如果“,”逗号是小于它应该只是跳过该行. eventreally安全正确的行.

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")

相关问题