我试图使用熊猫操作.csv文件,但我得到这个错误:

pandas.parser.CParserError:标记数据错误。C错误:第3行有2个字段,见12

我试着读过熊猫的文件,但一无所获。

我的代码很简单:

path = 'GOOG Key Ratios.csv'
#print(open(path).read())
data = pd.read_csv(path)

我该如何解决这个问题?我应该使用csv模块还是其他语言?

文件来自晨星公司


当前回答

检查是否使用正确的分隔符加载csv。

df = pd.read_csv(csvname, header=0, sep=",")

其他回答

我有一个类似的问题,而试图读取一个制表符分隔表与空格,逗号和引号:

1115794 4218    "k__Bacteria", "p__Firmicutes", "c__Bacilli", "o__Bacillales", "f__Bacillaceae", ""
1144102 3180    "k__Bacteria", "p__Firmicutes", "c__Bacilli", "o__Bacillales", "f__Bacillaceae", "g__Bacillus", ""
368444  2328    "k__Bacteria", "p__Bacteroidetes", "c__Bacteroidia", "o__Bacteroidales", "f__Bacteroidaceae", "g__Bacteroides", ""



import pandas as pd
# Same error for read_table
counts = pd.read_csv(path_counts, sep='\t', index_col=2, header=None, engine = 'c')

pandas.io.common.CParserError: Error tokenizing data. C error: out of memory

这表明它与C解析引擎(这是默认的)有关。也许换成python会改变一切

counts = pd.read_table(path_counts, sep='\t', index_col=2, header=None, engine='python')

Segmentation fault (core dumped)

这是一个不同的错误。 如果我们继续尝试从表中删除空格,来自python-engine的错误再次改变:

1115794 4218    "k__Bacteria","p__Firmicutes","c__Bacilli","o__Bacillales","f__Bacillaceae",""
1144102 3180    "k__Bacteria","p__Firmicutes","c__Bacilli","o__Bacillales","f__Bacillaceae","g__Bacillus",""
368444  2328    "k__Bacteria","p__Bacteroidetes","c__Bacteroidia","o__Bacteroidales","f__Bacteroidaceae","g__Bacteroides",""


_csv.Error: '   ' expected after '"'

很明显,熊猫在解析我们的行时遇到了问题。为了用python引擎解析一个表,我需要事先从表中删除所有的空格和引号。与此同时,c引擎不断崩溃,即使逗号在行。 为了避免创建一个带有替换的新文件,我这样做了,因为我的表很小:

from io import StringIO
with open(path_counts) as f:
    input = StringIO(f.read().replace('", ""', '').replace('"', '').replace(', ', ',').replace('\0',''))
    counts = pd.read_table(input, sep='\t', index_col=2, header=None, engine='python')

博士tl; 更改解析引擎,尽量避免在数据中使用任何非分隔的引号/逗号/空格。

在处理类似的解析错误时,我发现另一种方法很有用,它使用CSV模块将数据重新路由到pandas df。例如:

import csv
import pandas as pd
path = 'C:/FileLocation/'
file = 'filename.csv'
f = open(path+file,'rt')
reader = csv.reader(f)

#once contents are available, I then put them in a list
csv_list = []
for l in reader:
    csv_list.append(l)
f.close()
#now pandas has no problem getting into a df
df = pd.DataFrame(csv_list)

我发现CSV模块对于格式不佳的逗号分隔的文件更加健壮,因此已经成功地用这种方法解决了诸如此类的问题。

我相信解决方案,

,engine='python'
, error_bad_lines = False

如果它是虚拟列并且你想要删除它,这将是很好的。 在我的例子中,第二行确实有更多的列,我希望这些列被积分,并且有列数= MAX(列)。

请参考下面我无法阅读的解决方案:

try:
    df_data = pd.read_csv(PATH, header = bl_header, sep = str_sep)
except pd.errors.ParserError as err:
    str_find = 'saw '
    int_position = int(str(err).find(str_find)) + len(str_find)
    str_nbCol = str(err)[int_position:]
    l_col = range(int(str_nbCol))
    df_data = pd.read_csv(PATH, header = bl_header, sep = str_sep, names = l_col)

对我来说,问题是一个新列被附加到我的CSV盘中。如果我使用error_bad_lines=False,接受的答案解决方案将不起作用,因为未来的每一行都将被丢弃。

这种情况下的解决方案是使用pd.read_csv()中的usecols参数。通过这种方式,我可以只指定需要读入CSV中的列,并且只要标题列存在(并且列名不改变),我的Python代码将对未来的CSV更改保持弹性。

usecols : list-like or callable, optional Return a subset of the columns. If list-like, all elements must either be positional (i.e. integer indices into the document columns) or strings that correspond to column names provided either by the user in names or inferred from the document header row(s). For example, a valid list-like usecols parameter would be [0, 1, 2] or ['foo', 'bar', 'baz']. Element order is ignored, so usecols=[0, 1] is the same as [1, 0]. To instantiate a DataFrame from data with element order preserved use pd.read_csv(data, usecols=['foo', 'bar'])[['foo', 'bar']] for columns in ['foo', 'bar'] order or pd.read_csv(data, usecols=['foo', 'bar'])[['bar', 'foo']] for ['bar', 'foo'] order.

例子

my_columns = ['foo', 'bar', 'bob']
df = pd.read_csv(file_path, usecols=my_columns)

这样做的另一个好处是,如果我只使用一个有18-20列的CSV中的3-4列,我可以将更少的数据加载到内存中。

您的CSV文件可能有可变的列数,read_csv从前几行推断出列数。在这种情况下有两种解决方法:

1)将CSV文件更改为具有最大列数的虚拟第一行(并指定header=[0])

2)或者使用names = list(range(0,N)),其中N是最大列数。