df = pd.read_csv('somefile.csv')
...给出一个错误:
熊猫…/网站/ / io / parsers.py: 1130: DtypeWarning:列(4,5,7,16)为混合类型。指定dtype 选项导入或设置low_memory=False。
为什么dtype选项与low_memory相关,为什么low_memory=False帮助?
df = pd.read_csv('somefile.csv')
...给出一个错误:
熊猫…/网站/ / io / parsers.py: 1130: DtypeWarning:列(4,5,7,16)为混合类型。指定dtype 选项导入或设置low_memory=False。
为什么dtype选项与low_memory相关,为什么low_memory=False帮助?
当前回答
正如fireynx前面提到的,如果显式指定了dtype,并且存在与该dtype不兼容的混合数据,则加载将崩溃。我使用了这样的转换器作为变通方法来更改数据类型不兼容的值,这样数据仍然可以加载。
def conv(val):
if not val:
return 0
try:
return np.float64(val)
except:
return np.float64(0)
df = pd.read_csv(csv_file,converters={'COL_A':conv,'COL_B':conv})
其他回答
正如错误所示,在使用read_csv()方法时应该指定数据类型。 所以,你应该写
file = pd.read_csv('example.csv', dtype='unicode')
根据pandas文档,只要engine='c'(这是默认值),指定low_memory=False是这个问题的合理解决方案。
如果low_memory=False,则将首先读入整个列,然后确定正确的类型。例如,列将根据需要保存为对象(字符串)以保存信息。
If low_memory=True (the default), then pandas reads in the data in chunks of rows, then appends them together. Then some of the columns might look like chunks of integers and strings mixed up, depending on whether during the chunk pandas encountered anything that couldn't be cast to integer (say). This could cause problems later. The warning is telling you that this happened at least once in the read in, so you should be careful. Setting low_memory=False will use more memory but will avoid the problem.
就我个人而言,我认为low_memory=True是一个糟糕的默认值,但我工作的领域使用的小数据集比大数据集多得多,所以便利性比效率更重要。
下面的代码演示了一个示例,其中设置了low_memory=True,并且包含混合类型的列。它建立在@ fireynx的答案基础上
import pandas as pd
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
# make a big csv data file, following earlier approach by @firelynx
csvdata = """1,Alice
2,Bob
3,Caesar
"""
# we have to replicate the "integer column" user_id many many times to get
# pd.read_csv to actually chunk read. otherwise it just reads
# the whole thing in one chunk, because it's faster, and we don't get any
# "mixed dtype" issue. the 100000 below was chosen by experimentation.
csvdatafull = ""
for i in range(100000):
csvdatafull = csvdatafull + csvdata
csvdatafull = csvdatafull + "foobar,Cthlulu\n"
csvdatafull = "user_id,username\n" + csvdatafull
sio = StringIO(csvdatafull)
# the following line gives me the warning:
# C:\Users\rdisa\anaconda3\lib\site-packages\IPython\core\interactiveshell.py:3072: DtypeWarning: Columns (0) have mixed types.Specify dtype option on import or set low_memory=False.
# interactivity=interactivity, compiler=compiler, result=result)
# but it does not always give me the warning, so i guess the internal workings of read_csv depend on background factors
x = pd.read_csv(sio, low_memory=True) #, dtype={"user_id": int, "username": "string"})
x.dtypes
# this gives:
# Out[69]:
# user_id object
# username object
# dtype: object
type(x['user_id'].iloc[0]) # int
type(x['user_id'].iloc[1]) # int
type(x['user_id'].iloc[2]) # int
type(x['user_id'].iloc[10000]) # int
type(x['user_id'].iloc[299999]) # str !!!! (even though it's a number! so this chunk must have been read in as strings)
type(x['user_id'].iloc[300000]) # str !!!!!
旁白:举个例子说明这是一个问题(也是我第一次遇到这个严重问题的地方),假设你在一个文件上运行了pd.read_csv(),然后想要根据一个标识符删除副本。比如标识符有时是数字,有时是字符串。一行可能是“81287”,另一行可能是“97324-32”。不过,它们是唯一的标识。
如果使用low_memory=True, pandas可能会像这样读取标识符列:
81287
81287
81287
81287
81287
"81287"
"81287"
"81287"
"81287"
"97324-32"
"97324-32"
"97324-32"
"97324-32"
"97324-32"
因为它把东西分成很多块,有时标识符81287是数字,有时是字符串。当我试图基于此删除副本时,
81287 == "81287"
Out[98]: False
正如fireynx前面提到的,如果显式指定了dtype,并且存在与该dtype不兼容的混合数据,则加载将崩溃。我使用了这样的转换器作为变通方法来更改数据类型不兼容的值,这样数据仍然可以加载。
def conv(val):
if not val:
return 0
try:
return np.float64(val)
except:
return np.float64(0)
df = pd.read_csv(csv_file,converters={'COL_A':conv,'COL_B':conv})
Try:
dashboard_df = pd.read_csv(p_file, sep=',', error_bad_lines=False, index_col=False, dtype='unicode')
根据熊猫的文件:
dtype:列的类型名称或字典->类型
至于low_memory,默认为True,还没有文档。但我认为这无关紧要。错误消息是通用的,所以无论如何您都不需要处理low_memory。希望这对你有所帮助,如果你还有其他问题,请告诉我
已弃用的low_memory选项
low_memory选项没有被适当地弃用,但它应该被弃用,因为它实际上没有做任何不同的事情[来源]
得到这个low_memory警告的原因是为每一列猜测dtypes非常需要内存。Pandas试图通过分析每一列中的数据来确定要设置的dtype。
Dtype猜测(非常糟糕)
Pandas只能在读取整个文件时确定一个列应该具有什么dtype。这意味着在读取整个文件之前实际上无法解析任何内容,除非在读取最后一个值时必须冒险更改该列的dtype。
考虑一个文件的例子,该文件有一个名为user_id的列。 它包含1000万行,其中user_id总是数字。 由于pandas不能知道它只是数字,它可能会保留它作为原始字符串,直到它读取整个文件。
指定dtypes(应该总是这样做)
添加
dtype={'user_id': int}
到pd.read_csv()调用将使pandas知道当它开始读取文件时,这只是整数。
另外值得注意的是,如果文件的最后一行user_id列中写入了“foobar”,那么如果指定了上述dtype,加载将会崩溃。
定义dtypes时中断数据的示例
import pandas as pd
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
csvdata = """user_id,username
1,Alice
3,Bob
foobar,Caesar"""
sio = StringIO(csvdata)
pd.read_csv(sio, dtype={"user_id": int, "username": "string"})
ValueError: invalid literal for long() with base 10: 'foobar'
Dtypes通常是一个numpy的东西,在这里阅读更多关于它们的信息: http://docs.scipy.org/doc/numpy/reference/generated/numpy.dtype.html
存在哪些dtypes ?
我们可以访问numpy dtypes: float, int, bool, timedelta64[ns]和datetime64[ns]。注意,numpy日期/时间dtype不支持时区。
Pandas用它自己的dtype扩展了这组dtype:
'datetime64[ns, <tz>]'这是一个时区感知的时间戳。
'category',本质上是一个enum(由整数键表示的字符串保存
'period[]'不要与timedelta混淆,这些对象实际上被锚定到特定的时间段
'Sparse', 'Sparse[int]', 'Sparse[float]'是用于稀疏数据或'有很多洞的数据',而不是在数据框架中保存NaN或None,它省略了对象,节省空间。
'Interval'本身是一个主题,但它的主要用途是索引。点击这里查看更多信息
'Int8', 'Int16', 'Int32', 'Int64', 'UInt8', 'UInt16', 'UInt32', 'UInt64'都是可空的pandas特定整数,与numpy变体不同。
'string'是用于处理字符串数据的特定dtype,并允许访问该系列的.str属性。
'boolean'类似numpy 'bool',但它也支持缺失数据。
在这里阅读完整的参考资料:
Pandas dtype参考
陷阱,警告,注释
设置dtype=object将取消上述警告,但不会提高内存效率,只会提高进程效率。
设置dtype=unicode不会起任何作用,因为对numpy来说,unicode表示为对象。
转换器的使用
@sparrow正确地指出了转换器的用法,以避免在指定为int的列中遇到'foobar'时熊猫爆炸。我想补充一点,转换器在熊猫身上使用真的很重,效率也很低,应该作为最后的手段。这是因为read_csv进程是一个单独的进程。
CSV文件可以逐行处理,因此可以通过简单地将文件切割成段并运行多个进程来更有效地由多个转换器并行处理,这是pandas不支持的。但这是一个不同的故事。