【问题标题】:Python Pandas csv import "Error tokenizing data" - show error line contentPython Pandas csv 导入“错误标记数据” - 显示错误行内容
【发布时间】:2018-11-28 05:59:32
【问题描述】:

我正在读取一个大的 csv 文件

df = pd.read_csv(filename, sep=';',
                 encoding='cp850', quoting=3)

在某些行中,由于多余的分号,我收到了错误消息

Error tokenizing data. C error: 
Expected 33 fields in line 23836, saw 34

在 Vim 中打开文件时,大多数时候错误就在这一行。但有时不是在这个行号,而是在上面一行/几行。

如果我手动搜索该行,我会得到一个不同的行号,这是我在编辑器中找到错误的行号。

with open(filename, encoding='cp850') as f1:
    lines = f1.readlines()
    [(e, l) for e, l in enumerate(lines) 
        if len(split(';')) == 34] 

结果

[(23835, '.....

所以对于这个例子,错误不在第 23836 行,而是在第 23835 行。

read_csv的c和python引擎都会出现这个问题。

如果 read_csv 可以在错误消息中显示错误行内容将非常有帮助。

有没有办法做到这一点?

更新:

导入文件的行内似乎有换行符,如果一行被分成两行,read_csv 似乎接受这些行是正确的,因此在 33 个字段之后总是有一个换行符。但是从该行开始,错误消息中的行数不再匹配文件的换行符。

【问题讨论】:

  • 当您的标头长度小于某行中的值数时,此错误很常见。主要是由不适当的分隔符引起的
  • 它不会告诉您带有意外字段编号的行吗? Expected 33 fields in line 23836, saw 34这就是你发布的内容。
  • @SpghttCd 在这种情况下,错误是上面的一行。我的示例代码解释了这一点。此外,这不是由标题引起的,而是由文件组合了额外的分号和一些不属于的换行符引起的,我需要清理它们。这很难,因为我无法相信错误消息中的行号。
  • 您是否愿意在读取时忽略错误,然后在获得DataFrame 后过滤掉出现错误的行?
  • 不,我想查看错误并停止导入,但查看错误所在的行,以便修复并重新启动导入。

标签: python pandas csv


【解决方案1】:

出现错误的行是 csv 文件的第 23836 行,在 Python 中枚举时索引为 23835,因为 Python 是零索引的。

但是,错误的确切原因是什么?
如果它只是关于行,其中有一个或多个分号太多在末尾​​em>,那么您可以通过明确阅读前 33 列轻松地将它们丢弃:

df = pd.read_csv(filename, sep=';', usecols=range(33), encoding='cp850', quoting=3)

【讨论】:

  • 这无济于事,因为分号位于行中间的字段中。在其他情况下,如果字段包含不需要的换行符,则行号已关闭更多。所以这个问题的真正意义在于:你如何以最少的麻烦看到导致错误的行。
  • 嗯,这很糟糕。您能否发布错误行和一个好的示例,以便人们可以自己检查问题?而且我看到您故意停用报价,所以我认为这不是一个选项...?
  • 好吧,"how do you see the line that causes the error with the least amount of trouble"这个问题不难回答:"For example by reading the line number information in the error message of pd.read_csv()"
  • 这些是无法共享数据的外部文件。我必须导入它们,定位错误,修复它们直到它们导入。我可以像第二个示例那样编写代码,但我认为可能有一种方法可以告诉 pandas read_csv 显示它认为错误的行...
  • 无需发布机密或个人数据 - 尝试发布 结构,该结构与虚拟数据的好坏行不同 - 当然不是 33 列,而是两列或三个,仅举个例子……再说一遍:您是否了解 pandas已经提供了您感兴趣的行号
【解决方案2】:

从下面的坏行 23835 ± 2 行中创建一个包含匿名数据的示例文件:

import re
bad_idx = 23835
with open(filename, 'r') as f_in, open(filename[-4:] + '_dummy.csv', 'w') as f_out:
    for i, line in enumerate(f_in):
        line = re.sub('[a-zA-Z0-9]+', line)
        if (i > bad_idx-3) and (i < bad_idx+3) or i==0:
            f_out.write(line)

打印坏行及其行号列表(从 1 开始):

bad_lines = []
with open(filename, 'r') as f:
    n_col = len(f.readline().split(';'))
    for i, line in enumerate(f):
        if len(line.split(';')) != n_col:
            print(i+2, line)
            bad_lines.append(i+2)
print(bad_lines)

【讨论】:

    猜你喜欢
    • 2013-08-05
    • 2016-08-23
    • 1970-01-01
    • 2018-03-19
    • 2020-09-11
    • 2013-10-18
    • 1970-01-01
    相关资源
    最近更新 更多