读取CSV文件时混合类型的问题:原因、解决方案和后果

19 投票
2 回答
41255 浏览
提问于 2025-04-18 18:27

当Pandas发出这个警告时,具体发生了什么?我需要担心这个问题吗?

In [1]: read_csv(path_to_my_file)
/Users/josh/anaconda/envs/py3k/lib/python3.3/site-packages/pandas/io/parsers.py:1139: 
DtypeWarning: Columns (4,13,29,51,56,57,58,63,87,96) have mixed types. Specify dtype option on import or set low_memory=False.              

  data = self._reader.read(nrows)

我猜这意味着Pandas无法从这些列的值中推断出数据类型。但是如果真是这样的话,Pandas最后会用什么类型来处理这些列呢

另外,在收到警告后,数据类型是否总是可以恢复?(在收到警告之后)还是说有些情况下我可能无法正确恢复原来的信息,这时候我应该提前指定数据类型呢?

最后,low_memory=False是怎么解决这个问题的呢?

2 个回答

7

low_memory 这个选项现在好像有点过时了,所以我觉得没必要去用它。

这个警告的意思是,某一列里的值有的类型是一个(比如 str 字符串),有的类型又是另一个(比如 float 浮点数)。我记得 pandas 会使用一个最低的共同类型,举个例子就是 object

你应该检查一下你的数据,或者把一部分数据发到这里来。特别是要注意有没有缺失值,或者 int 整数和 float 浮点数的格式不一致。如果你确定你的数据是正确的,那就可以用 dtypes 这个参数来帮助 pandas 更好地处理数据。

19

重新查看mbatchkarov的链接,发现low_memory并没有被淘汰。现在它有了官方文档

low_memory : 布尔值,默认是True

这个选项会让程序在处理文件时分块进行,这样可以减少内存使用,但可能会导致数据类型判断不准确。如果你想确保没有混合类型,可以把它设置为False,或者用dtype参数来指定数据类型。需要注意的是,不管怎样,整个文件最终还是会读入一个完整的DataFrame中,如果想分块返回数据,可以使用chunksizeiterator参数。(这只适用于C解析器)

我问过“混合类型判断”是什么意思,chris-b1回答说:

这是确定的——数据中的类型会被一致地判断出来。不过,内部的chunksize并不是固定的行数,而是以字节为单位,所以你是否会收到混合数据类型的警告可能会有点随机。

那么,Pandas最终会为这些列使用什么类型呢?

这个问题可以通过下面的自包含示例来解答:

df=pd.read_csv(StringIO('\n'.join([str(x) for x in range(1000000)] + ['a string'])))
DtypeWarning: Columns (0) have mixed types. Specify dtype option on import or set low_memory=False.

type(df.loc[524287,'0'])
Out[50]: int

type(df.loc[524288,'0'])
Out[51]: str

CSV数据的第一部分被认为只有整数,所以转换成了整数;第二部分也有字符串,所以所有的条目都保留为字符串。

在收到警告后,类型能否总是恢复?

我想重新导出为CSV,然后用low_memory=False重新读取应该可以解决问题。

那么,low_memory=False到底是怎么解决这个问题的呢?

它会在决定数据类型之前先读取整个文件,因此需要更多的内存。

撰写回答