对于坏数据,Pandas dataframe read_csv

Fon*_*nti 49 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
Run Code Online (Sandbox Code Playgroud)

EdC*_*ica 77

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

error_bad_lines:boolean,default具有太多字段的True Lines(例如,带有太多逗号的csv行)默认情况下会引发异常,并且不会返回任何DataFrame.如果为False,那么这些"坏行"将从返回的DataFrame中删除.(仅对C解析器有效)

  • 另一种方法是读取一行以获得正确数量的cols,然后再次重新读取以读取那些列,例如`cols = pd.read_csv(file,nrows = 1).columns df = pd.read_csv(file, usecols = cols)`这将忽略我认为该错误行的附加列试试并让我知道它是否适合你 (2认同)
  • @Fonti:`truncate_bad_lines`没有选项.这样做是不好的做法.您假设您事先知道数据为何坏(它附加了额外的值).但如果它的列太少呢?如果插入额外的值而不是附加值怎么办?做这样的事情是一个错误的磁铁. (2认同)
  • 其实我只是试过这个,它不会工作,我认为你需要的是通过 `error_bad_lines=False` 并解析警告以获取行号并读取带有 `header=None` 的那些行 (2认同)

小智 35

对于像我这样在原件发布之后几年才遇到的人来说,其他答案建议使用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')
Run Code Online (Sandbox Code Playgroud)

on_bad_lines = 'warn'当遇到坏行时会发出警告并跳过该行。


其他可接受的on_bad_lines值是

  • 'error' 在坏线上引发异常
  • 'skip' 将跳过任何坏行


Luk*_*kas 18

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

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

'Skipping line 3: expected 4 fields, saw 3401\nSkipping line 4: expected 4 fields, saw 30...'
Run Code Online (Sandbox Code Playgroud)

如果您想保存警告消息(即进行一些进一步处理),那么您也可以将其保存到文件中(使用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)
Run Code Online (Sandbox Code Playgroud)


sit*_*uck 17

1.4.0 新增

首先pandas 1.4.0read_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
Run Code Online (Sandbox Code Playgroud)

以下 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
Run Code Online (Sandbox Code Playgroud)

可调用函数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
Run Code Online (Sandbox Code Playgroud)

功能定义

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
Run Code Online (Sandbox Code Playgroud)

结果

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
Run Code Online (Sandbox Code Playgroud)

  • @VeerajaVeeraesh `read_csv` 没有能力允许您跳过短行。 (2认同)