pandas中的read_csv函数在每行末尾带有分隔符时,index_col=None无法正常工作。

87

我正在阅读《Python数据分析》一书,在“示例:2012年联邦选举委员会数据库”章节中读取数据到DataFrame时遇到了问题。问题是,即使将index_col参数设置为None,数据的某一列始终被设置为索引列。

这里是数据链接:http://www.fec.gov/disclosurep/PDownload.do

这里是加载代码(为了节省检查时间,我设置了nrows=10):

import pandas as pd
fec = pd.read_csv('P00000001-ALL.csv',nrows=10,index_col=None)
为了简洁起见,我省略了数据列的输出,但这是我的输出(请注意索引值):
In [20]: fec

Out[20]:
<class 'pandas.core.frame.DataFrame'>
Index: 10 entries, C00410118 to C00410118
Data columns:
...
dtypes: float64(4), int64(3), object(11)

以下是该书的输出结果(仍然排除数据列):

In [13]: fec = read_csv('P00000001-ALL.csv')
In [14]: fec
Out[14]:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1001731 entries, 0 to 1001730
...
dtypes: float64(1), int64(1), object(14)

我的输出结果中的索引值实际上是文件中第一列数据,导致所有其他数据向左移动了一列。有人知道如何防止该数据列作为索引列?我希望索引只是递增的整数+1。

我对Python和Pandas都很新手,所以对任何不便表示歉意。谢谢。


这太糟糕了 - 也许他们在网站上最近几个月改变了CSV文件的形式(我自己没有进行任何修改)? - Wes McKinney
1
在我的情况下,我设置了index_col = 0,但它没有起作用,而index_col = None确实起作用了。 - parlad
2
在我的环境中,index_col=0 是有效的。而 index_col=Falseindex_col=None 则无效。 - dixhom
3个回答

135

快速答案

当每行末尾有分隔符时,使用index_col=False而不是index_col=None来关闭索引列推断并丢弃最后一列。

详细解释

在查看数据后,发现每行末尾都有逗号。此引用(自发布此帖子以来,文档已进行编辑):

index_col:要用作结果DataFrame的索引(行标签)的列号、列名或列号/列名列表。默认情况下,它将对行进行编号,而不使用任何列,除非数据列比标题多一个,这种情况下第一列将被视为索引。

文档中显示,pandas 认为您有n个表头和 n+1 个数据列,并将第一列作为索引。


编辑于 2014 年 10 月 20 日 - 更多信息

我找到了另一个有价值的条目,专门介绍了如何简单地忽略尾限定符:

如果一个文件有比列名数量多一个数据列,第一列将用作DataFrame的行名称:......

通常,您可以使用 index_col 选项来实现此行为。

但是,在某些例外情况下,一个文件可能已经准备好在每个数据行的末尾放置分隔符(译者注:即空列),这会使解析器感到困惑。要显式禁用索引列推断并丢弃最后一列,请传递 index_col=False: ......


你是对的。他所需要做的就是在标题末尾添加一个逗号,问题就会解决。我删除了我的帖子因为它是不正确的。 - juniper-
感谢craigts和juniper的帮助!最终,我将数据集中的最后一个列表项删除了,因为它们都是null。 - Rich
2
在我的情况下,index_col=0 apply。 - Shark Deng

105

回复craigts的回答,对于那些使用False或None参数来指定index_col出现困难的人,比如在试图去掉范围索引的情况下,您可以使用整数来指定要用作索引的列。例如:

df = pd.read_csv('file.csv', index_col=0)

上述代码将第一列设置为索引(并且不会添加范围索引到“常规情况”中)。
更新
鉴于这个答案的受欢迎程度,我想补充一些背景/演示:
# Setting up the dummy data
In [1]: df = pd.DataFrame({"A":[1, 2, 3], "B":[4, 5, 6]})

In [2]: df
Out[2]:
   A  B
0  1  4
1  2  5
2  3  6

In [3]: df.to_csv('file.csv', index=None)
File[3]:
A  B
1  4
2  5
3  6

如果没有使用 index_col 参数或者将其设置为 None/False,则读取的结果会得到一个区间索引:

In [4]: pd.read_csv('file.csv')
Out[4]:
   A  B
0  1  4
1  2  5
2  3  6

# Note that this is the default behavior, so the same as In [4]
In [5]: pd.read_csv('file.csv', index_col=None)
Out[5]:
   A  B
0  1  4
1  2  5
2  3  6

In [6]: pd.read_csv('file.csv', index_col=False)
Out[6]:
   A  B
0  1  4
1  2  5
2  3  6

然而,如果我们指定“ A”(第0列)实际上是索引,就可以避免范围索引:
In [7]: pd.read_csv('file.csv', index_col=0)
Out[7]:
   B
A
1  4
2  5
3  6

4
提醒一下,这与index_col=False在功能上并不相等。如果你希望数据集上有一个标准的整数索引,请使用false。如果你想使用第一列数据作为索引,请使用0。如果你想要在具有额外分隔符的数据集中将第一列数据作为索引,则需要设置usecols并指定index_col=0。我很快会扩展我的答案来涵盖这个问题。 - craigts
基于此,谢谢,这个对我有用。 - NoahVerner

2
如果pandas将第一行视为标题,则可以使用header = none进行如下设置:
df = pd.read_csv ("csv-file.csv", header=None)

这样做,pandas将把你的第一行视为任何一行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接