numpy、pandas内存优化操作整理

前言

python作为一款不怎么关注数据类型的语言,不同类型的数据可以往同一个变量中放置
这也就直接导致,作为熟悉C++这种一个变量只有一个类型的程序员来说,在解读python程序时,想搞清楚变量中到底存的是什么数据类型的时候时常很头疼
所以说,良好的编程习惯真的很重要
虽然上面的话跟这篇文章关系不大,但是我就是想吐槽一下 ;p
下面是我优化某个python项目的其中某个模块的内存时,对python中的numpy/pandas库调研得出的一些优化操作,在此分享给大家
:有的地方我理解的也不是很透彻,在此仅作为心得记录有任何不对的地方欢迎在评论区进行指正

一、通用优化操作

1. 指定合适的数据类型

如果数据的值域可以限制在较小的范围内,可手动指定其dtype类型进行限制

2. 避免copy

1)切片/索引层面

切片或其他索引方式中是否涉及拷贝,这部分就主要决定于各个库中具体实现细节了,可看下面对应章节部分

  • 原生python拷贝数组时注意的一个小细节:
    list1 = [...]1.类似浅拷贝/引用,操作对象为同一个,无copy,操作list2就是操作list1:
    list2 = list1
    2.类似深拷贝,涉及copy,list2与list1不是同一个对象:
    list2 = list1[:]
    

2)计算过程层面

如果输入数据可以“原地处理,且可以把计算过程拆分成“原地”处理的步骤,或是库里提供了可以“原地”计算的函数,则尽量进行拆分和替换“原地”处理的函数
下面是数组归一化时,将步骤进行拆分节省内存的一个例子:

  1. 简单的实现,但是会产生临时数组的内存开销
    def Normalize(lst : list):lst_range = lst.max - lst.minreturn (lst - lst.min) / lst_range
    
  2. 拆分步骤,每一步都是“原地”操作
    def Normalize(lst : list):lst_range = lst.max - lst.minlst -= lst.minlst /= lst_range
    

3. 文件读取

  • chunk读取:这个也算是流程优化的一部分
    读取文件时是否是一次性读取完毕?分块读取是否会影响到流程?如果可以分块读取,那么读取接口是否有提供类似chunksize的参数?
    一次读取的内容过多,一方面是会直接影响到IO内存,另一方面也是考虑到,大部分情况下实际要处理的数据并没有那么多,所以不如限制每次读取的数据大小,够用即可,用完再取
  • index索引:如果输入数据是有组织有结构地进行存储,那么通常可以通过建索引的方式记录数据的关键信息,在需要取用的时候就能通过索引快速取用自己所需的部分,一方面加速处理速度,另一方面内存也能更低

4. 数据结构的选取

主要是选用跟实际需求更匹配的数据结构,比如dict会浪费至少30%以上的内存,如果条件允许,可以通过一系列的方式对其进行优化

  1. 换用自定义class
  2. class + __slots__:加上限定,能省略class内的一些隐性内存开销
  3. namedtuple:同样是限定,但与tuple类似不可更改
  4. recordclass:基于namedtuple的可变变体(使用方式可看这里)

二、numpy相关

1. 使用sparse array

虽然ndarray适用于存储大量数据,但如果其中大部分数据都是空时,用稀疏矩阵能更省空间

2. 检查库方法的内部实现

库提供的方法为了泛用性,内部一般会对输入数据的类型进行限定,如果输入数据的类型与其预期不符,可能会造成更大的内存消耗
比如:一个库方法内部会将输入数据转为int64进行操作,如果输入的是int16,那么消耗内存会是int16 + int64,可能还不如把输入数据直接设置为int64并设置“原地”操作

3. indexing / slicing

numpy中有两种indexing方式,不同的方式返回值不同:可能返回view(类似浅拷贝/引用),也可能返回copy

  • 判断view/copy方式:可以简单地通过.base属性是否为None来判断
  • basic indexing:[]中为slice/integer或一个元组(包含slice/integer)时触发
    与python原生list切片不同,返回view
  • Advanced indexing:[]中为非元组sequence / ndarray( of integer/bool)或一个元组(包含至少一个sequence/ndarray)时触发
    返回copy
    示例:
    >>> import numpy as np
    >>> data1 = np.arange(9).reshape(3, 3)		# reshape returns a view at most time
    >>> data1
    array([[0, 1, 2],[3, 4, 5],[6, 7, 8]])
    >>> data1.base
    array([0, 1, 2, 3, 4, 5, 6, 7, 8])
    >>> 
    >>> data2 = data1[[1, 2]]					# data2 is a copy
    >>> data2
    array([[3, 4, 5],[6, 7, 8]])
    >>> data2.base
    >>> 
    >>> data1[[1, 2]]=[[10, 11, 12], [13, 14, 15]]	# change data1
    >>> data1							# 可能在 = 左边时不是copy?所以data1被改变了?
    array([[ 0,  1,  2],[10, 11, 12],[13, 14, 15]])
    >>> data2									# data2 not changed
    array([[3, 4, 5],[6, 7, 8]])
    
  • .reshape():在大部分情况下,如果可以通过修改步长的方式来重建数组则会返回view;如果数组变得不再连续了(即修改步长重建不了了,比如ndarray.transpose)则会返回copy

特殊情况:structured array

当ndarray的dtype使用named field时,该数组变成一个有结构的数组(类似DataFrame一样有名字,而且给每一列指定不同的dtype)

>>> x = np.array([('Rex', 9, 81.0), ('Fido', 3, 27.0)],dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
>>> x
array([('Rex', 9, 81.), ('Fido', 3, 27.)], dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])
  • Individual field:返回view
    >>> x['age']
    array([9, 3], dtype=int32)
    >>> x['age'] = 5
    >>> x
    array([('Rex', 5, 81.), ('Fido', 5, 27.)], dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])
    
  • Multiple fields:返回copy(版本<=1.15)或view(版本> 1.15)

4. 文件处理

numpy读取文件时可使用memmap对磁盘上的文件数据不读取到内存的同时当作ndarray一样去处理,但这个操作也存在一些限制:

  • 如果读取内容很大,那么这可能会成为程序的瓶颈,因为磁盘操作始终比内存操作要慢
  • 如果需要不同维度的索引/切片,那么只有符合默认结构的索引/切片会快,其余的会非常慢

解决方案:可选用其他文件读取库(如Zarr/HDF5)

三、pandas相关

1. 使用sparse array

与numpy类似,DataFrame同样可以设置成稀疏矩阵方式存储数据

2. [pyarrow]

pandas内部实际是使用numpy.ndarray来表示数据,但其对于 字符串缺失值 的处理并不友好
而在pandas版本2.1以后(至少2.0以后),引入的pyarrow可以极大地优化这两方面的处理

  • 原本numpy中是用一组PyObject*存储数据,额外空间开销大;而pyarrow中使用连续的char*数组存储,对于大量短字符串的优化效果尤其明显
  • 原本pandas中对于不同类型的缺失值有不同表示方式,而且对于整形的缺失值会自动转成浮点型,比较麻烦;而pyarrow中对不同类型都一套实现,数据的表示进行了统一

使用方式:实际使用时只需要在原本数据类型后面加上[pyarrow]即可。如:

  • string -> string[pyarrow]
  • int64 -> int64[pyarrow]
  • 读取接口处可以指定dtype_backend="pyarrow",有的还需指定engine="pyarrow"

3. indexing / slicing

非常重要的一点:pandas无法保证索引操作返回的是copy还是view
官方文档Copy on Write (CoW)的 previous behavior 小节第一句用了tricky to understand,可见它是有多难懂了
该页面主要介绍了让操作结果更加 predictable 的策略CoW,主要思路就是禁止在一行代码中更新多个对象
这样如果有多个对象实际指向同一份数据时,如果尝试更新其中一个对象的数据会触发copy,这样能保证另一份数据不会被影响;而且因为是更新时触发,尽量延缓了内存增加的时间
那么之前的代码中如果存在下面的操作时需格外注意,后续更新pandas版本后,结果可能与预期不符:

  • chained indexing
    一般表现为df[first_cond][second_cond] = ...,即对两个连续索引的结果进行更新
    因为df[first_cond]得到的不确定为copy还是view,所以这里实际不确定操作的是一个还是两个对象(具体可看Why does assignment fail when using chained indexing)
    chained indexing 官方示例
    :可能还有其他形式的 chained indexing 需要格外注意,比如CoW中还提到下面的形式:
    df[col].replace(..., inplace=True)
    
  • 解决办法:使用.loc取代多个索引(因为.loc操作能保证操作数据本身),或是将多个操作整合到一步操作中
    df.replace(col:{conditions}, inplace=True)
    or
    df[col] = df[col].replace(conditions)
    
    :如果DataFrame是Multi-Index的,那么两个连续索引相当于是使用.loc了,但是仍旧推荐使用.loc

4. 代码优化

  • 按行迭代:用itertuples替换iterrows(速度更快)
  • 循环操作:用.apply/.applymap替换循环
  • 大数据计算:使用pd.eval,在大数据上的较复杂计算才有速度优化效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/77815.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux本地&远程主机文件传输

一.实验环境 sshd 是SSH (Secure Shell)协议的守护进程。 功能用途 远程安全连接: sshd允许用户通过网络安全地登录到远程服务器。在传统的Telnet等协议中&#xff0c;数据传输是明文的&#xff0c; 容易被窃取和篡改。而SSH协议通过加密技术&#xff0c;对传输的数据进行加…

Windows网络及服务:制作系统盘

今天我要介绍的是一个比较有意思且好玩的一个小玩意儿&#xff1a;关于系统盘的制作&#xff1b; 注明&#xff1a;对于系统盘的制作&#xff0c;以及接下来的课程&#xff0c;基本是作为动手课业来进行的&#xff0c;这也是作为程序员的必要进行的一项活动。 对于系统盘&…

【人工智能】大模型的Prompt工程:释放DeepSeek潜能的艺术与科学

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 Prompt工程是大模型应用中的关键技术,通过精心设计的提示词(Prompt),用户能够有效引导模型生成高质量输出。本文深入探讨了优化DeepSee…

企业管理战略转型与模式创新策略

一、战略思维创新 在当前数字经济快速扩张的背景下&#xff0c;企业战略需紧密追随时代潮流&#xff0c;致力于深度创新以适应市场的瞬息万变。这一创新主要围绕两大战略核心展开&#xff0c;一是跨界融合策略&#xff0c;二是生态系统策略&#xff0c;它们共同塑造了企业在新…

1-1 什么是数据结构

1.0 数据结构的基本概念 数据结构是计算机科学中一个非常重要的概念&#xff0c;它是指在计算机中组织、管理和存储数据的方式&#xff0c;以便能够高效地访问和修改数据。简而言之&#xff0c;数据结构是用来处理数据的格式&#xff0c;使得数据可以被更有效地使用。 数据结构…

03-HTML常见元素

一、HTML常见元素 常见元素及功能&#xff1a; 元素用途<h1>~<h6>标题从大到小<p>段落&#xff0c;不同段落会有间距<img>显示图片&#xff0c;属性src为图片路径&#xff0c;alt为图片无法显示时的提示文本<a>超链接&#xff0c;属性href为链…

使用Cloudflare加速网站的具体操作步骤

要通过Cloudflare加速网站&#xff0c;您需要按照以下步骤进行设置和配置。这些步骤包括域名设置、接入Cloudflare、配置缓存和其他设置&#xff0c;以及测试网站性能。 1. 注册Cloudflare账户 访问Cloudflare官网&#xff1a;前往 Cloudflare官网。创建账户&#xff1a;点击…

C++算法(10):二叉树的高度与深度,(C++代码实战)

引言 在二叉树的相关算法中&#xff0c;高度&#xff08;Height&#xff09;和深度&#xff08;Depth&#xff09;是两个容易混淆的概念。本文通过示例和代码实现&#xff0c;帮助读者清晰区分二者的区别。 定义与区别 属性定义计算方式深度从根节点到该节点的边数根节点深度…

AI Agent开发第35课-揭秘RAG系统的致命漏洞与防御策略

第一章 智能客服系统的安全悖论 1.1 系统角色暴露的致命弱点 当用户以"你好"开启对话后追问"你之前说了什么",看似无害的互动实则暗藏杀机。2024年数据显示,93%的开源RAG系统在该场景下会完整复述初始化指令,导致系统角色定义(如电商导购)被完全暴露…

获取电脑信息(登录电脑的进程、C盘文件信息、浏览器信息、IP)

电脑的进程信息 // 获取登录电脑的进程信息String os System.getProperty("os.name").toLowerCase();String command;if (os.contains("win")) {command "tasklist";} else {command "ps -ef";}try {Process process new ProcessB…

如何在腾讯云Ubuntu服务器上部署Node.js项目

最近弄了一个Node.js项目&#xff0c;包含前端用户前台&#xff0c;管理后台和服务端API服务三个项目&#xff0c;本地搭建好了&#xff0c;于是在腾讯云上新建了个Ubuntu 24.04服务器&#xff0c;想要将本地的Node.js项目部署上去&#xff0c;包括环境配置和数据库搭建。 本文…

国产AI新突破!全球首款无限时长电影生成模型SkyReels-V2开源:AI视频进入长镜头时代!

在 AI 技术日新月异的今天&#xff0c;我们再次见证了历史性的突破。 昆仑万维 SkyReels 团队于近日正式发布了全球首款支持无限时长的电影生成模型——SkyReels-V2&#xff0c;并免费开源。这无疑为 AI 视频领域掀开了崭新的一页&#xff0c;标志着 AI 视频正式迈入长镜头时代…

SpringAI系列 - MCP篇(一) - 什么是MCP

目录 一、引言二、MCP核心架构三、MCP传输层(stdio / sse)四、MCP能力协商机制(Capability Negotiation)五、MCP Client相关能力(Roots / Sampling)六、MCP Server相关能力(Prompts / Resources / Tools)一、引言 之前我们在接入大模型时,不同的大模型通常都有自己的…

一个很简单的机器学习任务

一个很简单的机器学习任务 前言 基于线上colab做的一个简单的案例&#xff0c;应用了线性回归算法&#xff0c;预测了大概加州3000多地区的房价中位数 过程 先导入了Pandas&#xff0c;这是一个常见的Python数据处理函数库 用Pandas的read_csv函数把网上一个共享数据集&…

【第十六届 蓝桥杯 省 C/Python A/Java C 登山】题解

题目链接&#xff1a;P12169 [蓝桥杯 2025 省 C/Python A/Java C] 登山 思路来源 一开始想的其实是记搜&#xff0c;但是发现还有先找更小的再找更大的这种路径&#xff0c;所以这样可能错过某些最优决策&#xff0c;这样不行。 于是我又想能不能从最大值出发往回搜&#xf…

软件工程师中级考试-上午知识点总结(上)

我总结的这些都是每年的考点&#xff0c;必须要记下来的。 1. 计算机系统基础 1.1 码 符号位0表示正数&#xff0c;符号位1表示负数。补码&#xff1a;简化运算部件的设计&#xff0c;最适合进行数字加减运算。移码&#xff1a;与前几种不同&#xff0c;1表示&#xff0c;0表…

Python Cookbook-6.7 有命名子项的元组

任务 Python 元组可以很方便地被用来将信息分组&#xff0c;但是访问每个子项都需要使用数字索引&#xff0c;所以这种用法有点不便。你希望能够创建一种可以通过名字属性访问的元组。 解决方案 工厂函数是生成符合要求的元组的子类的最简单方法: #若在2.4中可使用operator…

win10设置软件开机自启

参考教程&#xff1a;windows10应用程序设置了开机启动&#xff0c;但没有自启_win10软件设置了自启动但是不能自启动-CSDN博客 主要设置是安全策略&#xff1a;

自注意力机制、多头自注意力机制、填充掩码 Python实现

原理讲解 【Transformer系列&#xff08;2&#xff09;】注意力机制、自注意力机制、多头注意力机制、通道注意力机制、空间注意力机制超详细讲解 自注意力机制 import torch import torch.nn as nn# 自注意力机制 class SelfAttention(nn.Module):def __init__(self, input…

【大模型】Browser-Use AI驱动的浏览器自动化工具

Browser-Use AI驱动的浏览器自动化工具 1. 项目概述2. 核心架构3. 实战指南3.1 环境安装3.2 快速启动3.3 进阶功能 4. 常见问题与解决5. 项目优势与局限6. 扩展资源7. 总结 1. 项目概述 项目地址&#xff1a;browser-use Browser-Use 是一个开源工具&#xff0c;旨在通过 AI 代…