Pandas Parser将多个csv文件读取到HDF5时出现EOF字符错误



使用Python3,Pandas 0.12

我正在尝试将多个csv文件(总大小为7.9 GB)写入HDF5存储区,以便稍后处理。csv文件每个包含大约一百万行,15列,数据类型大多是字符串,但也有一些浮动。然而,当我试图读取csv文件时,我会收到以下错误:

Traceback (most recent call last):
  File "filter-1.py", line 38, in <module>
    to_hdf()
  File "filter-1.py", line 31, in to_hdf
    for chunk in reader:
  File "C:Python33libsite-packagespandasioparsers.py", line 578, in __iter__
    yield self.read(self.chunksize)
  File "C:Python33libsite-packagespandasioparsers.py", line 608, in read
    ret = self._engine.read(nrows)
  File "C:Python33libsite-packagespandasioparsers.py", line 1028, in read
    data = self._reader.read(nrows)
  File "parser.pyx", line 706, in pandas.parser.TextReader.read (pandasparser.c:6745)
  File "parser.pyx", line 740, in pandas.parser.TextReader._read_low_memory (pandasparser.c:7146)
  File "parser.pyx", line 781, in pandas.parser.TextReader._read_rows (pandasparser.c:7568)
  File "parser.pyx", line 768, in pandas.parser.TextReader._tokenize_rows (pandasparser.c:7451)
  File "parser.pyx", line 1661, in pandas.parser.raise_parser_error (pandasparser.c:18744)
pandas.parser.CParserError: Error tokenizing data. C error: EOF inside string starting at line 754991
Closing remaining open files: ta_store.h5... done 

编辑

我设法找到了一个产生这个问题的文件。我觉得这是在读一个EOF角色。然而,我不知道如何克服这个问题。考虑到组合文件的大尺寸,我认为检查每个字符串中的每个字符太麻烦了。(即便如此,我仍然不确定该怎么办。)据我检查,csv文件中没有可能引发错误的奇怪字符。我还尝试将error_bad_lines=False传递给pd.read_csv(),但错误仍然存在。

我的代码如下:

# -*- coding: utf-8 -*-
import pandas as pd
import os
from glob import glob

def list_files(path=os.getcwd()):
    ''' List all files in specified path '''
    list_of_files = [f for f in glob('2013-06*.csv')]
    return list_of_files

def to_hdf():
    """ Function that reads multiple csv files to HDF5 Store """
    # Defining path name
    path = 'ta_store.h5'
    # If path exists delete it such that a new instance can be created
    if os.path.exists(path):
        os.remove(path)
    # Creating HDF5 Store
    store = pd.HDFStore(path)
    # Reading csv files from list_files function
    for f in list_files():
        # Creating reader in chunks -- reduces memory load
        reader = pd.read_csv(f, chunksize=50000)
        # Looping over chunks and storing them in store file, node name 'ta_data'
        for chunk in reader:
            chunk.to_hdf(store, 'ta_data', mode='w', table=True)
    # Return store
    return store.select('ta_data')
    return 'Finished reading to HDF5 Store, continuing processing data.'
to_hdf()

编辑

如果我进入引发CParserError EOF的CSV文件。。。并手动删除导致问题的行之后的所有行,csv文件将正确读取。然而,我删除的都是空白行。奇怪的是,当我手动更正错误的csv文件时,它们会被单独加载到商店中。但是当我再次使用多个文件的列表时,"false"文件仍然会返回错误。

我也遇到了类似的问题。用'EOF inside string'列出的行有一个字符串,其中包含一个单引号(')。当我添加选项quoting=csv.QUOTE_NONE时,它解决了我的问题。

例如:

import csv
df = pd.read_csv(csvfile, header = None, delimiter="t", quoting=csv.QUOTE_NONE, encoding='utf-8')

我也有同样的问题,在将这两个参数添加到我的代码中后,问题就消失了。

read_csv(…quoting=3error_bad_lines=False

我意识到这是一个老问题,但我想分享更多关于这个错误的根本原因以及@Selah的解决方案为什么有效的细节。

来自csv.py文档字符串:

    * quoting - controls when quotes should be generated by the writer.
    It can take on any of the following module constants:
    csv.QUOTE_MINIMAL means only when required, for example, when a
        field contains either the quotechar or the delimiter
    csv.QUOTE_ALL means that quotes are always placed around fields.
    csv.QUOTE_NONNUMERIC means that quotes are always placed around
        fields which do not parse as integers or floating point
        numbers.
    csv.QUOTE_NONE means that quotes are never placed around fields.

csv.QUOTE_MINIMAL为默认值,"为默认quotechar。如果csv文件中的某个地方有一个quotechar,它将被解析为字符串,直到再次出现quotechar。如果您的文件有奇数个quotechar,那么在到达EOF(文件末尾)之前,最后一个quotechars将不会关闭。还要注意,quotechar之间的任何内容都将被解析为单个字符串。即使有许多换行符(预计将被解析为单独的行),它们都会进入表的单个字段。因此,你在错误中得到的行号可能会产生误导。举例说明:

In[4]: import pandas as pd
  ...: from io import StringIO
  ...: test_csv = '''a,b,c
  ...: "d,e,f
  ...: g,h,i
  ...: "m,n,o
  ...: p,q,r
  ...: s,t,u
  ...: '''
  ...: 
In[5]: test = StringIO(test_csv)
In[6]: pd.read_csv(test)
Out[6]: 
                 a  b  c
0  d,e,fng,h,inm  n  o
1                p  q  r
2                s  t  u
In[7]: test_csv_2 = '''a,b,c
  ...: "d,e,f
  ...: g,h,i
  ...: "m,n,o
  ...: "p,q,r
  ...: s,t,u
  ...: '''
  ...: test_2 = StringIO(test_csv_2)
  ...: 
In[8]: pd.read_csv(test_2)
Traceback (most recent call last):
...
...
pandas.errors.ParserError: Error tokenizing data. C error: EOF inside string starting at line 2

第一个字符串有2个(偶数)引号。因此,每个quotechar都是关闭的,csv被解析时没有错误,尽管可能不是我们所期望的。另一个字符串有3个(奇数)引号。最后一个没有关闭,达到EOF,因此出现错误。但我们在错误信息中看到的第2行是误导性的。我们期望4,但由于第一个和第二个quotechar之间的所有内容都被解析为字符串,所以我们的"p,q,r行实际上是第二行。

这样做的内部循环将允许您检测"坏"文件(并进一步调查)

from pandas.io import parser
def to_hdf():
    .....
    # Reading csv files from list_files function
    for f in list_files():
        # Creating reader in chunks -- reduces memory load
        try:
            reader = pd.read_csv(f, chunksize=50000)
            # Looping over chunks and storing them in store file, node name 'ta_data'
            for chunk in reader:
                chunk.to_hdf(store, 'ta_data', table=True)
        except (parser.CParserError) as detail:
             print f, detail

解决方案是在read_csv函数中使用参数engine='ython'。Pandas CSV解析器可以使用两个不同的"引擎"来解析CSV文件——Python或C(这也是默认的)。

pandas.read_csv(filepath, sep=',', delimiter=None, 
            header='infer', names=None, 
            index_col=None, usecols=None, squeeze=False, 
            ..., engine=None, ...)

在Pandas文档中,Python引擎被描述为"较慢,但功能更完整"。

engine : {‘c’, ‘python’}

我的错误:

ParserError:标记数据时出错。C错误:字符串中存在EOF从第4488'行开始

通过在我的代码中添加delimiter="t"解决为:

import pandas as pd
df = pd.read_csv("filename.csv", delimiter="t")

使用

engine="python",
error_bad_lines=False,

在CCD_ 15上。

完整的通话内容如下:

df = pd.read_csv(csvfile, 
                 delimiter="t", 
                 engine="python",
                 error_bad_lines=False,  
                 encoding='utf-8')

对我来说,其他解决方案不起作用,让我非常头疼。error_bad_lines=False仍然给出错误C error: EOF inside string starting at line。使用不同的引号也没有得到想要的结果,因为我不想在文本中使用引号。

我意识到Pandas 0.20中有一个错误。升级到0.21版本完全解决了我的问题。有关此错误的更多信息,请参阅:https://github.com/pandas-dev/pandas/issues/16559

注意:这可能与URL中提到的Windows相关。

在查找了几个小时的解决方案后,我终于找到了一个解决方案。

在不降低多处理效率的情况下消除这种C error: EOF inside string starting at line exception的最佳方法是对输入数据进行预处理(如果有这样的机会)。

替换输入文件中的所有"\n"项,例如"、"或任何其他唯一符号序列(例如"aghr21*&")。然后,您将能够将数据读取到数据帧中。

读取数据后,您可能需要将所有唯一的符号序列('aghr21*&')替换回'\n'。

在尝试从Github存储库提取数据时遇到了类似的问题。一个简单的错误是,试图从git blob(html呈现的部分)而不是原始csv中提取数据。

如果您从git repo中提取数据,请确保您的链接不包括<repo name>/blob,除非您对repo中的html代码特别感兴趣。

不涉及数据丢失的最简单解决方案是:

df = pd.read_csv(nome_do_arquivo, sep=",")

最新更新