在 Pandas read_csv 期间标记数据时出错。如何真正看到坏线?

Posted

技术标签:

【中文标题】在 Pandas read_csv 期间标记数据时出错。如何真正看到坏线?【英文标题】:Error tokenizing data during Pandas read_csv. How to actually see the bad lines? 【发布时间】:2016-12-18 13:23:48 【问题描述】:

我有一个大的 csv,我按如下方式加载

df=pd.read_csv('my_data.tsv',sep='\t',header=0, skiprows=[1,2,3])

我在加载过程中遇到了几个错误。

    首先,如果我不指定warn_bad_lines=True,error_bad_lines=False,我会得到:

    标记数据时出错。 C 错误:预计第 329867 行中有 22 个字段,见 24

    其次,如果我使用上面的选项,我现在得到:

    CParserError:标记数据时出错。 C 错误:字符串中的 EOF 从第 32357585 行开始

问题是:我如何查看这些坏线以了解发生了什么?是否有可能让read_csv 返回这些虚假行?

我尝试了以下提示 (Pandas ParserError EOF character when reading multiple csv files to HDF5):

from pandas import parser

try:
  df=pd.read_csv('mydata.tsv',sep='\t',header=0, skiprows=[1,2,3])
except (parser.CParserError) as detail:
  print  detail

但还是得到了

标记数据时出错。 C 错误:预计第 329867 行中有 22 个字段,见 24

【问题讨论】:

你检查了第一个答案吗?会是特殊字符吗? ***.com/questions/18016037/… 第 32357585 行的数据是什么?这可能会提供一些线索并检查熊猫版本,github.com/pydata/pandas/issues/11654 是的,这就是问题所在。如何读取这条数据线? 如果是 CSV,在 CSV 中打开它(假设是 windows 框)(或)使用其他一些文件读取 API 来首先打印和理解数据,一旦你知道那里有什么,那么你可以尝试使用 pandas 找到解决方法。 Pandas 读取前几行,确定 dtypes,然后读取确定的 dtypes 中的其余数据。有时这会导致对字符串的误解。 low_memory 只会导致 pandas 在读取所有数据后创建数据类型。它会导致内存中的数据重复。但你是对的,它可能对你的情况没有帮助。其他建议怎么样? 【参考方案1】:

我将分两部分给出答案:

第 1 部分: 操作员询问如何输出这些坏行,要回答这个问题,我们可以在这样的简单代码中使用 python csv 模块:

import csv
file = 'your_filename.csv' # use your filename
lines_set = set([100, 200]) # use your bad lines numbers here

with open(file) as f_obj:
    for line_number, row in enumerate(csv.reader(f_obj)):
        if line_number > max(lines_set):
            break
        elif line_number in lines_set: # put your bad lines numbers here
            print(line_number, row)

我们也可以把它放在更通用的函数中:

import csv


def read_my_lines(file, lines_list, reader=csv.reader):
    lines_set = set(lines_list)
    with open(file) as f_obj:
        for line_number, row in enumerate(csv.reader(f_obj)):
            if line_number > max(lines_set):
                break
            elif line_number in lines_set:
                print(line_number, row)


if __name__ == '__main__':
    read_my_lines(file='your_filename.csv', lines_list=[100, 200])

part2:你得到错误的原因:

如果没有您使用的文件样本,就很难诊断出这样的问题。 但你应该试试这个..

pd.read_csv(filename)

它解析文件没有错误吗?如果是这样,我会解释原因。

列数是从第一行推断出来的。

通过使用 skiprows 和 header=0,您转义了前 3 行,我猜它包含列名或应该包含正确列数的标题。

基本上你限制了解析器正在做什么。

所以解析时不要跳过,或者 header=0 然后重新索引到您以后需要的内容。

注意

如果您不确定文件中使用的分隔符使用sep=None,但它会更慢。

来自 pandas.read_csv 文档:

sep : str,默认使用“,”分隔符。如果 sep 为 None,则 C 引擎 不能自动检测分隔符,但是python解析 引擎可以,这意味着后者将被使用并自动检测 Python 的内置嗅探器工具 csv.Sniffer 的分隔符。在 此外,超过 1 个字符且不同于 '\s+' 的分隔符 将被解释为正则表达式,也会强制使用 Python 解析引擎。请注意,正则表达式分隔符很容易出现 忽略引用的数据。正则表达式示例:'\r\t'

link

【讨论】:

【参考方案2】:

就我而言,添加分隔符有帮助:

data = pd.read_csv('/Users/myfile.csv', encoding='cp1251', sep=';')

【讨论】:

【参考方案3】:

我们可以从错误中获取行号并打印行以查看它的样子

试试:

import subprocess
import re
from pandas import parser

try:
  filename='mydata.tsv'
  df=pd.read_csv(filename,sep='\t',header=0, skiprows=[1,2,3])
except (parser.CParserError) as detail:
  print  detail
  err=re.findall(r'\b\d+\b', detail) #will give all the numbers ['22', '329867', '24'] line number is at index 1
  line=subprocess.check_output("sed -n %s %s" %(str(err[1])+'p',filename),stderr=subprocess.STDOUT,shell=True) # shell command 'sed -n 2p filename'  for printing line 2 of filename
  print 'Bad line'
  print line # to see line 

【讨论】:

以上是关于在 Pandas read_csv 期间标记数据时出错。如何真正看到坏线?的主要内容,如果未能解决你的问题,请参考以下文章

在 csv 导入 pandas 期间跳过行

pandas使用read_csv函数读取文件时指定数据列的数据类型pandas使用read_csv函数读取文件时通过keep_default_na参数设置缺失值替换为空字符串

详解pandas的read_csv()

如何在使用 pandas.read_csv 读取 csv 文件时将 pandas.dataframe 中的元素转换为 np.float?

如何在使用 pandas.read_csv 读取 csv 文件时将 pandas.dataframe 中的元素转换为 np.float?

处理 Pandas read_csv 中的缺失数据