使用 on_bad_lines 将 pandas.read_csv 中的无效行写入文件

Grr*_*sss 2 python csv pandas

我有一个 CSV 文件,我正在使用 Python 来解析该文件。我发现文件中的某些行具有不同的列数。

001;Snow,Jon;19801201
002;Crom,Jake;19920103
003; ;Wise,Frank;19880303   <-- Invalid row
004;Wiseau,Tommy;4324;1323;2323  <-- Invalid row
Run Code Online (Sandbox Code Playgroud)

我想将这些无效行写入单独的文本文件中。

我使用这行代码从文件中读取。

df = pd.read_csv('names.csv', header=None,sep=';')
Run Code Online (Sandbox Code Playgroud)

我在这里找到的一种解决方案是使用以下代码跳过有问题的行:

data = pd.read_csv('file1.csv', on_bad_lines='skip')
Run Code Online (Sandbox Code Playgroud)

我可以从“跳过”更改为“警告”,这将给出有问题的行的行号并跳过该行。但这将返回警告消息,而不是行本身。

Rom*_*est 9

由于pandas1.4.0 允许callable使用on_bad_lines参数 - 这允许您对坏行应用更复杂的处理。

1.4.0版本新增:

callable, function with signature (bad_line: list[str]) -> list[str] | None that will process a single bad line. bad_line is a
Run Code Online (Sandbox Code Playgroud)

按 sep 分割的字符串列表。如果函数返回 None,则坏行将被忽略。如果该函数返回一个新的字符串列表,其元素多于预期,则在删除额外元素时将发出 ParserWarning。仅当 engine="python" 时支持


因此,您可以传递一个自定义函数,该函数会将遇到的错误行写入特定文件并返回None(在数据帧生成时跳过该行)。

from functools import partial

def write_bad_line(line, fp, sep=','):
    fp.write(sep.join(line) + '\n')
    return None  # return None to skip the line while processing

bad_lines_fp = open('bad_lines.csv', 'a')
df = pd.read_csv('test.csv', header=None, sep=';', engine='python',
                 on_bad_lines=partial(write_bad_line, sep=';', fp=bad_lines_fp))
bad_lines_fp.close()
print(df)
Run Code Online (Sandbox Code Playgroud)

数据帧的输出:

   0          1         2
0  1   Snow,Jon  19801201
1  2  Crom,Jake  19920103
Run Code Online (Sandbox Code Playgroud)

内容bad_lines.csv(通过cat命令):

$ cat bad_lines.csv
003; ;Wise,Frank;19880303
004;Wiseau,Tommy;4324;1323;2323
Run Code Online (Sandbox Code Playgroud)