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帮助?


当前回答

已弃用的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不支持的。但这是一个不同的故事。

其他回答

df = pd.read_csv('somefile.csv', low_memory=False)

这应该能解决问题。当从CSV中读取1.8M行时,我得到了完全相同的错误。

正如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})

根据Jerald Achaibar给出的答案,我们可以检测混合Dytpes警告,并且只在警告发生时使用较慢的python引擎:

import warnings

# Force mixed datatype warning to be a python error so we can catch it and reattempt the 
# load using the slower python engine
warnings.simplefilter('error', pandas.errors.DtypeWarning)
try:
    df = pandas.read_csv(path, sep=sep, encoding=encoding)
except pandas.errors.DtypeWarning:
    df = pandas.read_csv(path, sep=sep, encoding=encoding, engine="python")

这对我很管用!

file = pd.read_csv('example.csv', engine='python')

已弃用的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不支持的。但这是一个不同的故事。