pandas 字符串存儲技術演進:從 object 到 PyArrow 的十年歷程

文章目錄

    • 1. 引言
    • 2. 階段1:原始時代(pandas 1.0前)
    • 3. 階段2:Python-backed StringDtype(pandas 1.0 - 1.3)
    • 4. 階段3:PyArrow初次嘗試(pandas 1.3 - 2.1)
    • 5. 階段4:過渡方案pyarrow_numpy(pandas 2.1 - 2.3)
    • 6. 階段5:全面轉向PyArrow(pandas 2.0+及未來3.0)
    • 7. 結論


在數據分析領域,字符串數據是最常見的數據類型之一。無論是處理文本文件、數據庫查詢結果,還是網頁抓取的內容,字符串都承載著大量有價值的信息。而pandas作為Python生態中最受歡迎的數據處理庫,其對字符串的存儲和處理能力,直接影響著數據分析的效率和效果。在過去的十年里,pandas的字符串存儲技術經歷了多次重要的變革,從最初簡單的object類型存儲,逐步發展到基于PyArrow的高效存儲方案。本文將沿著這一技術演進的脈絡,深入探討每一個階段的特點、問題以及帶來的改進。

1. 引言

字符串處理在數據分析中的核心地位不言而喻。在實際應用中,我們經常需要對字符串進行清洗、轉換、匹配等操作。例如,在處理電商交易數據時,商品名稱、客戶地址等都是字符串類型;在自然語言處理任務中,文本內容更是以字符串的形式存在。高效的字符串存儲和處理技術,能夠顯著提升數據分析的速度,減少內存占用,從而提高整個分析流程的效率。

隨著數據規模的不斷增大,pandas早期的字符串存儲技術逐漸暴露出性能和內存管理上的不足。為了適應大數據時代的需求,pandas字符串存儲技術的演進勢在必行。這不僅是技術發展的必然要求,也是為了更好地滿足用戶在實際數據分析工作中的需求。

2. 階段1:原始時代(pandas 1.0前)

在pandas 1.0版本之前,字符串數據默認使用object數據類型(dtype)進行存儲。object dtype本質上是存儲Python字符串對象的引用,缺失值則使用np.nan表示。這種存儲方式簡單直接,但也帶來了一系列嚴重的問題。

從內存占用角度來看,object dtype的效率非常低。假設有一個包含100萬個字符串的Series,每個字符串平均長度為10個字符,使用object dtype存儲時,其內存占用約為80MB。這是因為每個Python字符串對象除了存儲實際的字符數據外,還需要額外的內存來存儲對象的元數據,如引用計數、類型信息等。

在性能方面,基于object dtype的字符串操作也十分緩慢。以將所有字符串轉換為大寫為例,使用str.upper()方法對100萬個字符串進行操作,耗時大約需要2.1秒。這是因為object dtype下的字符串操作本質上是對Python對象進行循環操作,無法充分利用底層的向量化計算優勢。

此外,object dtype還存在混合類型的隱患。由于object dtype可以存儲任意Python對象,當Series中同時存在字符串、整數、浮點數等不同類型的數據時,整個Series都會被轉換為object dtype。這不僅會導致性能下降,還可能引發一些難以排查的錯誤。

下面通過一段代碼來直觀感受object dtype的存儲和性能問題:

import pandas as pd
import numpy as np
import time# 創建包含100萬個字符串的Series
data = [f"string_{i}" for i in range(1000000)]
s = pd.Series(data)# 查看數據類型
print(s.dtype)  # object# 記錄開始時間
start_time = time.time()
# 將字符串轉換為大寫
s = s.str.upper()
# 記錄結束時間
end_time = time.time()
print(f"轉換為大寫耗時: {end_time - start_time} 秒") # 查看內存占用
print(f"內存占用: {s.memory_usage(index=True, deep=True) / (1024 * 1024):.2f} MB")

3. 階段2:Python-backed StringDtype(pandas 1.0 - 1.3)

為了解決object dtype在字符串存儲上的一些問題,pandas 1.0版本引入了StringDtype,其中StringDtype("python")是基于Python對象的實現。這種存儲方式強制將數據存儲為字符串類型或者pd.NA(用于表示缺失值),明確了類型邊界,統一了缺失值語義。

object dtype相比,StringDtype("python")在類型檢查和缺失值處理上更加嚴格和規范。例如,當嘗試將非字符串類型的數據存入StringDtype的Series時,pandas會拋出類型錯誤,而不是像object dtype那樣將數據強制轉換為對象。同時,pd.NA的引入,使得缺失值的處理更加統一,避免了np.nan在不同數據類型下可能產生的歧義。

然而,StringDtype("python")本質上仍然是基于Python對象的存儲,因此在內存占用和性能上與object dtype相比并沒有本質的提升。它只是在類型管理和缺失值處理上進行了優化,并沒有解決底層存儲效率和計算性能的問題。

通過以下代碼可以體驗StringDtype("python")的特點:

import pandas as pd# 創建使用StringDtype("python")的Series
s = pd.Series(["apple", "banana", pd.NA], dtype="string[python]")
print(s.dtype)  # string[python]# 嘗試存入非字符串類型數據,會拋出類型錯誤
try:s[0] = 1
except TypeError as e:print(f"錯誤信息: {e}")

4. 階段3:PyArrow初次嘗試(pandas 1.3 - 2.1)

pandas 1.3版本開始引入StringDtype("pyarrow"),這是一個基于Apache Arrow的字符串存儲方案。Apache Arrow是一個跨語言的內存數據格式,它采用列式內存布局,能夠高效地存儲和處理數據。基于PyArrow的字符串存儲,使得pandas在字符串處理上有了質的飛躍。

在內存占用方面,使用StringDtype("pyarrow")存儲100萬個字符串,內存占用可以降至28MB左右。這是因為PyArrow采用了更加緊湊的內存布局,避免了Python對象額外的元數據開銷。在性能上,同樣是將100萬個字符串轉換為大寫,使用StringDtype("pyarrow")str.upper()操作耗時可以縮短至0.25秒,大幅提升了處理速度。

此外,基于PyArrow的存儲方案還帶來了零拷貝生態兼容的優勢。它可以與其他基于Arrow的庫(如Dask、Vaex等)進行無縫協作,避免了數據在不同庫之間轉換時的拷貝開銷,進一步提高了數據處理的效率。

不過,StringDtype("pyarrow")也存在一些問題。其中最主要的是缺失值語義的沖突。StringDtype("pyarrow")使用pd.NA表示缺失值,而在pandas的傳統體系中,很多操作和函數仍然依賴np.nan來表示缺失值,這就導致在一些混合場景下,缺失值的處理會出現不兼容的情況。

下面通過代碼展示StringDtype("pyarrow")的性能和內存優勢:

import pandas as pd
import time# 創建使用StringDtype("pyarrow")的Series
data = [f"string_{i}" for i in range(1000000)]
s = pd.Series(data, dtype="string[pyarrow]")# 記錄開始時間
start_time = time.time()
# 將字符串轉換為大寫
s = s.str.upper()
# 記錄結束時間
end_time = time.time()
print(f"轉換為大寫耗時: {end_time - start_time} 秒") # 查看內存占用
print(f"內存占用: {s.memory_usage(index=True, deep=True)/ (1024 * 1024):.2f} MB")

5. 階段4:過渡方案pyarrow_numpy(pandas 2.1 - 2.3)

為了解決StringDtype("pyarrow")在缺失值語義上與傳統np.nan的沖突問題,pandas 2.1版本引入了pyarrow_numpy存儲方案。pyarrow_numpy采用PyArrow進行字符串存儲,但使用np.nan表示缺失值,通過強制轉換的方式來兼容傳統的缺失值語義。

這種設計的動機是為了在保證性能提升的同時,解決混合場景下的兼容性問題。在實際應用中,很多用戶的代碼和工作流程已經習慣了使用np.nan來處理缺失值,如果突然完全改用pd.NA,可能會導致大量代碼需要修改。pyarrow_numpy的出現,為用戶提供了一個過渡方案,使得他們可以在享受PyArrow帶來的性能優勢的同時,繼續使用熟悉的缺失值處理方式。

然而,pyarrow_numpy方案也存在一定的局限性。由于需要在PyArrow存儲和np.nan缺失值之間進行額外的轉換邏輯,這會導致一定的性能妥協。例如,使用pyarrow_numpy存儲100萬個字符串,內存占用大約為35MB,str.upper()操作耗時約為0.4秒,相比純粹的StringDtype("pyarrow"),性能有所下降。

通過以下代碼可以了解pyarrow_numpy的使用和性能情況:

import pandas as pd
import time# 創建使用pyarrow_numpy的Series
data = [f"string_{i}" for i in range(1000000)]
s = pd.Series(data, dtype="string[pyarrow_numpy]")# 記錄開始時間
start_time = time.time()
# 將字符串轉換為大寫
s = s.str.upper()
# 記錄結束時間
end_time = time.time()
print(f"轉換為大寫耗時: {end_time - start_time} 秒")# 查看內存占用
print(f"內存占用: {s.memory_usage(index=True, deep=True) / (1024 * 1024):.2f} MB")

6. 階段5:全面轉向PyArrow(pandas 2.0+及未來3.0)

從pandas 2.0版本開始,字符串存儲逐步向PyArrow全面過渡。在pandas 2.0及以上版本中,默認會推斷出string[pyarrow]類型,并且在缺失值處理上,也逐漸兼容np.nan。這意味著用戶在使用pandas處理字符串數據時,無需手動指定存儲類型,就能享受到PyArrow帶來的性能優勢,同時在缺失值處理上也更加靈活。

對于未來的pandas 3.0版本,官方計劃強制使用PyArrow進行字符串存儲,并移除pyarrow_numpy過渡方案。這一舉措將進一步簡化pandas的字符串存儲體系,提高整體的性能和穩定性。同時,全面轉向PyArrow也有助于更好地與其他大數據處理庫(如Dask、PySpark)進行生態整合,實現數據在不同庫之間的無縫流轉和高效處理。

在實際應用中,用戶可以通過以下代碼體驗pandas 2.0+版本中默認的string[pyarrow]存儲:

import pandas as pd# 創建Series,pandas會自動推斷為string[pyarrow]類型
s = pd.Series(["apple", "banana", None])
print(s.dtype)  # string[pyarrow]

7. 結論

階段時間范圍存儲方式核心特點解決的問題
原始時代pandas 1.0 前object dtypePython 字符串對象存儲,np.nan 缺失值無專門字符串類型,混合類型問題嚴重
Python-backed StringDtypepandas 1.0 - 1.3StringDtype("python")強制字符串/pd.NA,但仍基于 Python 對象解決混合類型問題,但性能無提升
PyArrow 初次嘗試pandas 1.3 - 2.1StringDtype("pyarrow")Arrow 存儲,pd.NA 缺失值高性能、低內存,但與傳統 np.nan 不兼容
過渡方案 pyarrow_numpypandas 2.1 - 2.3StringDtype("pyarrow_numpy")Arrow 存儲,np.nan 缺失值臨時解決缺失值語義沖突,但性能妥協
全面轉向 PyArrowpandas 2.0+(3.0 默認)StringDtype("pyarrow")Arrow 存儲,兼容 np.nan 缺失值統一高性能、低內存、生態兼容,替代所有舊方案

回顧pandas字符串存儲技術的十年演進歷程,我們可以清晰地看到其發展的核心驅動力:性能、兼容性和生態整合。從最初簡單的object dtype,到逐步引入基于Python對象的StringDtype,再到基于PyArrow的高效存儲方案,每一次技術變革都是為了更好地解決實際應用中遇到的問題。

未來,隨著pandas 3.0版本全面強制使用PyArrow進行字符串存儲,PyArrow將成為pandas字符串處理的事實標準。這不僅會進一步提升pandas在字符串處理上的性能和效率,還將加強其與大數據生態的融合,為用戶提供更加統一、高效的數據處理體驗。對于數據分析從業者來說,了解和掌握pandas字符串存儲技術的演進,將有助于更好地應對日益復雜和大規模的數據處理任務。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/86300.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/86300.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/86300.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[特殊字符] 在 React Native 項目中封裝 App Icon 一鍵設置命令(支持參數與默認路徑)

?? 前置依賴 使用的是社區維護的 CLI 工具: @bam.tech/react-native-make它擴展了 react-native 命令,支持 set-icon 功能。 安裝: yarn add -D "@bam.tech/react-native-make"?? 封裝目標 我們希望能夠通過以下方式調用: # 默認使用 ./icon.png yarn …

[論文閱讀] 人工智能 | 搜索增強LLMs的用戶偏好與性能分析

【論文解讀】Search Arena:搜索增強LLMs的用戶偏好與性能分析 論文信息 作者: Mihran Miroyan, Tsung-Han Wu, Logan King等 標題: Search Arena: Analyzing Search-Augmented LLMs 來源: arXiv preprint arXiv:2506.05334v1, 2025 一、研究背景:…

[2025CVPR]確定性圖像轉換新突破:雙逼近器布朗橋模型(Dual-approx Bridge)技術詳解

本文深入解析CVPR 2024頂會論文《Deterministic Image-to-Image Translation via Denoising Brownian Bridge Models with Dual Approximators》,揭示確定性圖像轉換的核心突破 一、問題背景:確定性圖像轉換的挑戰 在圖像轉換任務中(如超分辨率、醫學影像處理),?確定性…

Python Pytest

1.Pytest用例發現規則 1.1 模塊名(python文件)名必須以 test_ 開頭或 _test 結尾,如 test_case,case_test,下劃線都不能少 1.2 模塊不能放在 . 開頭的隱藏目錄或者叫 venv的目錄下,virtual environment,叫venv1都可以…

CSRF(跨站請求偽造)詳解

目錄 一、📖什么是CSRF 二、🔗漏洞利用過程 三、📑漏洞的前提條件 四、🔍常見漏洞發生位置 五、?CSRF挖掘技巧 (一) 抓正常請求包進行初步判斷 (二) Referer 繞過驗證測試 (三) Token 缺失與二次驗證缺失識別 六、??漏…

深入解析 Qwen3-Embedding 的模型融合技術:球面線性插值(Slerp)的應用

在深度學習領域,模型融合技術是一種強大的工具,用于提升模型的魯棒性和泛化能力。通過結合多個模型的優勢,可以減少單一模型的過擬合風險,并在多種任務中實現更優的性能表現。在 Qwen3-Embedding 的訓練過程中,模型融合…

【在線五子棋對戰】二、websocket 服務器搭建

文章目錄 Ⅰ. WebSocket1、簡介2、特點3、原理解析4、報文格式 Ⅱ. WebSocketpp1、認識2、常用接口3、websocketpp庫搭建服務器搭建流程主體框架填充回調函數細節 4、編寫 makefile 文件5、websocket客戶端 Ⅰ. WebSocket 1、簡介 WebSocket 是從 HTML5 開始支持的一種網頁端…

針對異構數據的聯邦學習

在聯邦學習中,數據異構性是指不同客戶端之間的數據分布差異,包括數據的特征空間、標簽空間以及數據量等方面的差異。處理異構數據是聯邦學習中的一個重要挑戰,因為異構數據可能導致模型訓練過程中的性能不穩定、收斂速度較慢,甚至…

【判斷自整除數】2022-4-6

緣由是判斷自整除數的,這個我的結果是正確的,但是提交就有運行錯誤是怎么回事啊-編程語言-CSDN問答 void 自整除數字() {//所謂的自整除數字就是該數字可以整除其每一個位上的數字。 //對一個整數n,如果其各個位數的數字相加得到的數m能整除n,則稱n為自…

@Import原理與實戰

文章目錄 前言一、導入普通類二、導入ImportSelector實現類三、導入ImportBeanDefinitionRegistrar實現類四、Import注解的解析4.1、解析實現ImportSelector的候選bean4.2、解析實現ImportBeanDefinitionRegistrar的候選bean4.3、DeferredImportSelector的特殊處理 總結 前言 I…

day 18進行聚類,進而推斷出每個簇的實際含義

浙大疏錦行 對聚類的結果根據具體的特征進行解釋,進而推斷出每個簇的實際含義 兩種思路: 你最開始聚類的時候,就選擇了你想最后用來確定簇含義的特征, 最開始用全部特征來聚類,把其余特征作為 x,聚類得到…

Java并發編程實戰 Day 11:并發設計模式

【Java并發編程實戰 Day 11】并發設計模式 開篇 這是"Java并發編程實戰"系列的第11天,今天我們聚焦于并發設計模式。并發設計模式是解決多線程環境下常見問題的經典解決方案,它們不僅提供了優雅的設計思路,還能顯著提升系統的性能…

iview組件庫:當后臺返回到的數據與使用官網組件指定的字段不匹配時,進行修改某個屬性名再將response數據渲染到頁面上的處理

1、需求導入 當存在前端需要的數據的字段渲染到表格或者是一些公共的表格組件展示數據時的某個字段名與后臺返回的字段不一致時,那么需要前端進行稍加處理,而不能直接this.list res.data;這樣數據是渲染不出來的。 2、后臺返回的數據類型 Datalist(pn) …

Ubuntu下有關UDP網絡通信的指令

1、查看防火墻狀態: sudo ufw status # Ubuntu 2、 檢查系統全局廣播設置 # 查看是否忽略廣播包(0表示接收,1表示忽略) sysctl net.ipv4.icmp_echo_ignore_broadcasts# 查看是否允許廣播轉發(1表示允許&#xff09…

vue3:十六、個人中心-修改密碼

一、頁面效果 頁面展示當前用戶名(只讀),展示需要輸入的當前密碼,輸入新的密碼以及確認密碼的提交表單 二、初始建立 1、建立密碼修改頁面 在個人中心文件夾中寫入新頁面UpdatepwdView.vue 2、新建路由 在路由頁面中寫入修改密碼頁面 3、新建菜單 在菜單布局菜單頁面中寫…

GitFlow 工作模式(詳解)

今天再學項目的過程中遇到使用gitflow模式管理代碼,因此進行學習并且發布關于gitflow的一些思考 Git與GitFlow模式 我們在寫代碼的時候通常會進行網上保存,無論是github還是gittee,都是一種基于git去保存代碼的形式,這樣保存代碼…

【Vue3】(三)vue3中的pinia狀態管理、組件通信

目錄 一、vue3的pinia 二、【props】傳參 三、【自定義事件】傳參 四、【mitt】傳參 五、【v-model】傳參(平常基本不寫) 六、【$attrs】傳參 七、【$refs和$parent】傳參 八、provide和inject 一、vue3的pinia 1、什么是pinia? pinia …

【DAY43】復習日

內容來自浙大疏錦行python打卡訓練營 浙大疏錦行 作業: kaggle找到一個圖像數據集,用cnn網絡進行訓練并且用grad-cam做可視化 進階:并拆分成多個文件

xtp+ctp 交易系統接口簡介

CTP(上海期貨交易所綜合交易平臺)和 XTP(中泰證券極速交易平臺)是中國金融市場中兩個重要的證券期貨交易系統,它們在定位、架構和應用場景上有顯著區別: 1. 開發主體與服務領域 維度CTPXTP開發公司上海期貨…

阿里云Alibaba Cloud安裝Docker與Docker compose【圖文教程】

個人記錄 進入控制臺,找到定時與自動化任務 進入‘安裝/卸載擴展程序’ 點擊‘安裝擴展程序’ 選擇docker社區版,點擊下一步與確定,等待一會 安裝成功 查詢版本 查詢docker sudo docker version查詢docker compose sudo docker compo…