Pandas read_csv:low_memory 和 dtype 选项

2025-01-03 08:41:00
admin
原创
274
摘要:问题描述:df = pd.read_csv('somefile.csv') ...出现错误:.../site-packages/pandas/io/parsers.py:1130: DtypeWarning: 列 (4,5,7,16) 具有混合类型。导入时指定 dtype 选项或设置 low_memory=F...

问题描述:

df = pd.read_csv('somefile.csv')

...出现错误:

.../site-packages/pandas/io/parsers.py:1130: DtypeWarning: 列 (4,5,7,16) 具有混合类型。导入时指定 dtype 选项或设置 low_memory=False。

为什么该dtype选项与相关low_memory,以及为什么可能会有low_memory=False帮助?


解决方案 1:

已弃用的 low_memory 选项

low_memory选项没有被适当弃用,但应该被弃用,因为它实际上并没有做任何不同的事情[来源]

收到此low_memory警告的原因在于猜测每列的数据类型非常耗费内存。Pandas 会尝试通过分析每列中的数据来确定要设置的数据类型。

数据类型猜测(非常糟糕)

只有在读取整个文件后,Pandas 才能确定列应具有什么数据类型。这意味着在读取整个文件之前无法真正解析任何内容,除非您在读取最后一个值时冒险更改该列的数据类型。

考虑一个文件的示例,该文件有一列名为 user_id。它包含 1000 万行,其中 user_id 始终为数字。由于 pandas 无法知道它只是数字,因此它可能会将其保留为原始字符串,直到读取整个文件为止。

指定数据类型(应该始终完成)

添加

dtype={'user_id': int}

pd.read_csv()调用将使 pandas 知道何时开始读取文件,这只是整数。

还值得注意的是,如果文件的最后一行写入了"foobar"该列user_id,则如果指定了上述 dtype,加载就会崩溃。

定义 dtype 时损坏的数据示例

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

存在哪些数据类型?

我们可以访问 numpy dtypes:float、int、bool、timedelta64[ns] 和 datetime64[ns]。请注意,numpy 日期/时间 dtypes 不支持时区。

Pandas 用自己的数据类型扩展了这组数据类型:

'datetime64[ns, <tz>]'这是一个时区感知的时间戳。

“类别”本质上是一个枚举(用整数键表示的字符串来保存

'period[]' 不要与 timedelta 混淆,这些对象实际上锚定在特定的时间段

'Sparse'、'Sparse[int]'、'Sparse[float]' 用于稀疏数据或“其中存在大量漏洞的数据”,它不会在数据框中保存 NaN 或 None,而是省略对象,从而节省空间。

“间隔”本身就是一个主题,但其主要用途是索引。更多内容请见此处

'Int8'、'Int16'、'Int32'、'Int64'、'UInt8'、'UInt16'、'UInt32'、'UInt64' 都是 pandas 特定的可空整数,与 numpy 变体不同。

“string” 是一种用于处理字符串数据的特定数据类型,可以访问.str系列上的属性。

“boolean” 与 numpy 的“bool”类似,但它也支持缺失数据。

在这里阅读完整的参考资料:

Pandas 数据类型参考

陷阱、警告、说明

设置dtype=object将会消除上述警告,但不会使其更节省内存,只会提高进程效率。

设置dtype=unicode不会执行任何操作,因为对于 numpy 来说,aunicode表示为object

转换器的使用

@sparrow 正确地指出了转换器的用法,以避免 pandas 在遇到'foobar'指定为 的列时崩溃int。我想补充一点,转换器在 pandas 中使用起来确实很重而且效率低下,应该作为最后的手段。这是因为 read_csv 过程是一个单一过程。

CSV 文件可以逐行处理,因此只需将文件切分为多个部分并运行多个进程,即可更高效地由多个转换器并行处理,而 Pandas 不支持此功能。但这是另一个故事。

解决方案 2:

尝试:

dashboard_df = pd.read_csv(p_file, sep=',', error_bad_lines=False, index_col=False, dtype='unicode')

根据熊猫文档:

dtype :列的类型名称或字典 -> 类型

至于 low_memory,默认情况下它为 True ,并且尚未记录。不过我认为它并不相关。错误消息是通用的,所以你无论如何都不需要处理 low_memory。希望这能有所帮助,如果您有其他问题,请告诉我

解决方案 3:

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

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

解决方案 4:

这对我有用!

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

解决方案 5:

正如 firelynx 之前提到的,如果明确指定了 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})

解决方案 6:

它在导入 DataFrame 时对我有用low_memory = False。这就是对我有用的所有更改:

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

解决方案 7:

在处理大型 csv 文件(600 万行)时,我遇到了类似的问题。我遇到了三个问题:

  1. 该文件包含奇怪的字符(使用编码修复)

  2. 未指定数据类型(使用 dtype 属性修复)

  3. 使用上述方法我仍然面临一个与无法根据文件名定义的 file_format 相关的问题(使用 try.. except.. 修复)

    df = pd.read_csv(csv_file,sep=';', encoding = 'ISO-8859-1',
                     names=['permission','owner_name','group_name','size','ctime','mtime','atime','filename','full_filename'],
                     dtype={'permission':str,'owner_name':str,'group_name':str,'size':str,'ctime':object,'mtime':object,'atime':object,'filename':str,'full_filename':str,'first_date':object,'last_date':object})
    
    try:
        df['file_format'] = [Path(f).suffix[1:] for f in df.filename.tolist()]
    except:
        df['file_format'] = ''

解决方案 8:

有时候,当所有其他方法都失败时,你只想告诉熊猫闭嘴:

# Ignore DtypeWarnings from pandas' read_csv                                                                                                                                                                                            
warnings.filterwarnings('ignore', message="^Columns.*")

解决方案 9:

根据pandas 文档,low_memory=False只要指定engine='c'(这是默认值)就是该问题的合理解决方案。

如果low_memory=False,则将首先读入整个列,然后确定适当的类型。例如,将根据需要将列保留为对象(字符串)以保存信息。

如果low_memory=True(默认),则 pandas 会以行块的形式读取数据,然后将它们附加在一起。然后,某些列可能看起来像是混合的整数和字符串块,这取决于 pandas 在块期间是否遇到任何无法转换为整数的内容 (比如说)。这可能会在以后引起问题。警告告诉您这种情况在读取过程中至少发生过一次,因此您应该小心。设置low_memory=False将使用更多内存,但可以避免出现问题。

就我个人而言,我认为low_memory=True这是一种糟糕的默认设置,但我的工作领域使用的小数据集比大数据集多得多,因此便利性比效率更重要。

以下代码说明了设置了 并且列包含混合类型的示例low_memory=True。它基于 @firelynx 的答案

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
"
csvdatafull = "user_id,username
" + csvdatafull

sio = StringIO(csvdatafull)
# the following line gives me the warning:
    # C:Users
disaanaconda3libsite-packagesIPythoncoreinteractiveshell.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

解决方案 10:

正如错误所说,你应该在使用该read_csv()方法时指定数据类型。因此,你应该写

file = pd.read_csv('example.csv', dtype='unicode')

解决方案 11:

我遇到了一个类似的问题,文件大小约为 400MB。设置low_memory=False对我来说很管用。先做简单的事情,我会检查你的数据框是否不大于你的系统内存,重新启动,清除 RAM 然后再继续。如果你仍然遇到错误,那么值得确保你的.csv文件没有问题,快速查看 Excel 并确保没有明显的损坏。损坏的原始数据会造成严重破坏……

解决方案 12:

根据 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")

解决方案 13:

这对我有用!

dashboard_df = pd.read_csv(p_file, sep=';', error_bad_lines=False, index_col=False, dtype='unicode')
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用