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.pswp.cn/bicheng/77815.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/77815.shtml
英文地址,請注明出處:http://en.pswp.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 代…