提问者:Josh,2014 Jun 16 at 19:56
当处理
df = pd.read_csv('somefile.csv')
我得到
\Users\Python\Python36\python.exe E:/Python/111.py
sys:1: DtypeWarning: Columns (3) have mixed types. Specify dtype option on import or set low_memory=False.
low_memory为毛跟dtype扯上关系了?还有就是设定False就能解决问题的原理是什么?
回答者:firelynx,Dec 1 '14 at 16:04
low_memory选项再次没有被恰当地废掉,但是真心该废,因为实际上没起啥用(source_link)
你得到low_memory警示的原因就是pandas推测各字段dtypes(数据类型)很占内存:对字段里的每个数据都分析确定dtype。
只有在整个文件读取完了Pandas才能确定字段的dtype。这意味着在读取完之前,啥信息都解析不到,除非你在读完某字段最后一个值那一刻冒险更改该字段的dtype。
举个栗子看,比如有个含有user_id字段的10000万行大小的文件,通常user_id都是数字类型。因为pandas不清数它是否全是数字,在读取玩整个文件前,pandas可能会把它先当成字符串类型处理。
在pd.read_csv()里边加dtype={'user_id':int},pandas在开始读取数据时就知道了:它全是int类型数据。
不过当user_id含有字符串类型数比如“foobar”的时候,这个方法就不仅没啥用,还会把读取进程弄崩溃。就像这样:
import pandas as pd
from StringIO import StringIO
csvdata =
"""
user_id, username
1, Alice
3, Bob
foobar, Caesar
"""
sio = StringIO(csvdata)
pd.read_csv(sio, dtype={"user_id":int, "username":object})
ValueError: invalidliteral for long() with base 10:'foobar'
dtype是个典型的numpy库的事儿,具体细节看这:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html
这些是numpy,也是在pandas里用的
[numpy.generic,
[[numpy.number,
[[numpy.integer,
[[numpy.signedinteger,
[numpy.int8,
numpy.int16,
numpy.int32,
numpy.int64,
numpy.int64,
numpy.timedelta64]],
[numpy.unsignedinteger,
[numpy.uint8,
numpy.uint16,
numpy.uint32,
numpy.uint64,
numpy.uint64]]]],
[numpy.inexact,
[[numpy.floating,
[numpy.float16, numpy.float32, numpy.float64, numpy.float128]],
[numpy.complexfloating,
[numpy.complex64, numpy.complex128, numpy.complex256]]]]]],
[numpy.flexible,
[[numpy.character, [numpy.bytes_, numpy.str_]],
[numpy.void, [numpy.record]]]],
numpy.bool_,
numpy.datetime64,
numpy.object_]]
Pandas自己又弄了2个:categorical和datetime64[ns, tz],numpy里边不能用。
Pandas字符类型查阅链接
设定dtype=object之后可以消除上边的Low-memory警告,但是在提高memory efficiency上没有作用,非要说有作用的话那就是对process efficiency而言。
设定dtype=unicode啥用都没有,因为对于numpy来说(pandas可以说是定制版Numpy),一个unicode被当做object对象的。
如sparrow指出的,转换函数确实可以让程序在处理如被转换为int格式字段中的“foobar”时不报错,这很对。我想补充的是,转换函数在pandas上运行起来很笨重、效率很低,不到万不得已就不用。因为read_csv是单线程的。
csv格式可以一行一行处理的,通过分割成多个部分来进行多线程处理,但是pandas不支持。这就是另个一个话题了这里不讨论。