资讯动态

pandas PDEP-10 解读:PyArrow 如何成为 pandas 3.0 默认字符串推断实现的基础依赖

发布时间:2026/9/19 20:08:13 来源:尧图企业网站定制
pandas PDEP-10 解读PyArrow 如何成为 pandas 3.0 默认字符串推断实现的基础依赖【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas导读本文围绕 pandas 项目中的设计提案 PDEP-10PyArrow as a required dependency for default string inference implementation展开系统梳理 pandas 将 PyArrow 从可选依赖推向默认依赖的完整决策过程从版本演进时间线、三条即时用户收益、未来收益与代价权衡到 FAQ 中关于默认推断边界的澄清并结合当前仓库源码如 pandas/compat/_optional.py、pyproject.toml、pandas/core/config_init.py验证提案的最终落地形态。读完本文你将理解 pandas 3.0 中字符串数据默认推断为str/string[pyarrow]类型背后的设计动机、性能依据与取舍逻辑以及如何在代码中提前适配这一行为变更。一、PDEP-10 提案概览PDEP-10 是 pandas 官方设计提案Pandas Enhancement Proposal系列中的第 10 号提案于2023 年 4 月 17 日创建状态为Accepted已接受由 Matthew Roeschke 与 Patrick Hoefler 共同撰写完整原文位于 web/pandas/pdeps/0010-required-pyarrow-dependency.md。该提案的核心诉求可以浓缩为四条PyArrow 自 pandas 3.0 起成为必需required的运行时依赖pandas 3.0 支持的 PyArrow 最低版本为 7当最低版本被提升时遵循提升到已发布至少 2 年的最高版本的版本策略从 pandas 3.0 起字符串数据的默认推断类型从object变为ArrowDtype底层为pyarrow.string并同步推断下文列出的其他数据类型而不再一律存为object。重要前置说明硬依赖已被推迟PDEP-10 文档开篇有一条醒目的 note需特别关注虽然本提案最初计划在 pandas 3.0 中将 PyArrow 列为必需依赖但这一硬依赖目标已被推迟到 pandas 3.0 之后详见 PDEP-14 的摘要。因此实际状态是pandas 3.0 不会对 PyArrow 构成硬性要求但当环境中安装了 PyArrow 时会默认使用它用于新的字符串 dtype。也就是说必须安装降级为装了就用、默认推荐这一调整主要回应了社区对安装体积与复杂度的反馈。渐进式迁移时间线PDEP-10 规划了一条清晰的警告与迁移路径版本节点动作pandas 2.1发布说明中给出大字号警告PyArrow 将在 pandas 3.0 成为必需依赖并固定一个反馈 issue注释指向该 issuepandas 2.2当环境中未安装 PyArrow 时导入 pandas 抛出一次FutureWarning保证只警告一次、可轻松静默警告同样指向反馈 issuepandas 3.0字符串数据默认推断为 PyArrow 支撑的string[pyarrow]而非object同时默认推断下述其他数据类型二、BackgroundPyArrow 与 pandas 的集成编年史PDEP-10 用一段清晰的版本时间线说明了 PyArrow 早已深度嵌入 pandas 的方方面面pandas 0.21.0PyArrow 提供 Parquet 的 I/O 读取功能pandas 1.2.0pandas 将 PyArrow 集成进ExtensionArray接口提供由 PyArrow 支撑的可选字符串数据类型pandas 1.4.0PyArrow 提供 CSV 的 I/O 读取功能pandas 1.5.0pandas 提供ArrowExtensionArray与ArrowDtype在ExtensionArray接口内支持全部 PyArrow 数据类型pandas 2.0.0所有 I/O 读取器都支持返回 PyArrow 支撑的数据类型大量方法开始利用 PyArrow 的 compute 函数加速 PyArrow 支撑的数据尤其是字符串与日期时间类型。截至 pandas 2.0用户已经可以切实地把 PyArrow 作为 NumPy 的替代数据表示使用其优势包括所有数据类型都有一致的NA缺失值支持更广泛的数据类型支持例如decimal、date以及嵌套类型list、struct 等与其他基于 Arrow 的 dataframe 库具有更好的互操作性。这些能力在当时都是可选的——用户需要显式指定才会生效。PDEP-10 的核心主张就是既然集成已如此深入不如顺势而为。三、动机为 Arrow 生态投出信任票pandas 官方路线图明确写有更好的 Apache Arrow 互操作性这一长期目标参见 doc/source/development/roadmap.rst 相关章节且 Python 生态内外已有大量项目在采用或交互 Arrow 格式。在此背景下把 PyArrow 提升为必需依赖本质上是 pandas对 Arrow 生态的一次表态——既增强了 pandas 与其他 Arrow 系库互操作的信心也简化了 pandas 内部围绕 Arrow 的开发路径。四、三大即时用户收益4.1 收益一PyArrow 字符串终结objectdtype 的性能灾难现状是当用户向 pandas 构造函数传入字符串数据且不指定 dtype 时结果类型是object。而object类型相比 PyArrow 字符串内存占用与性能都差得多In [1]: import pandas as pd In [2]: pd.Series([a]).dtype # 当前行为 Out[2]: dtype(O) # pandas 3.0 中的未来行为 Out[2]: string[pyarrow]PDEP-10 内附了一个百万级字符串的性能演示脚本import string import random import pandas as pd def random_string() - str: return .join(random.choices(string.printable, krandom.randint(10, 100))) ser_object pd.Series([random_string() for _ in range(1_000_000)]) ser_string ser_object.astype(string[pyarrow])文档中记录的实测数据PyArrow 字符串显著快于 NumPy object 字符串str.lenIn[1]: %timeit ser_object.str.len() 118 ms ± 260 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) In[2]: %timeit ser_string.str.len() 24.2 ms ± 187 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)str.startswithIn[3]: %timeit ser_object.str.startswith(a) 136 ms ± 300 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) In[4]: %timeit ser_string.str.startswith(a) 11 ms ± 19.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)以文档数据为参照str.len提速约5 倍str.startswith提速约12 倍。PDEP 中引用了 Dask 开发者对 PyArrow 字符串在性能与内存上的调研结论——相较当前objectdtype 是显著的改进。这也是整个提案最直接、最有说服力的用户收益。4.2 收益二嵌套数据类型Nested Datatypes自动推断当前若把dict存入Series得到的同样是低效的objectdtypeIn [6]: pd.Series([{a: 1, b: 2}, {a: 2, b: 99}]) Out[6]: 0 {a: 1, b: 2} 1 {a: 2, b: 99} dtype: object如果 PyArrow 成为必需依赖这类数据本可被自动推断为pyarrow.struct同样带来内存与性能的双重改善。4.3 收益三与其他 Arrow 系 dataframe 库的互操作性其他 Arrow 支撑的 dataframe 库如 polars正在快速增长。若 pandas 与它们共享同一套内存表示那么类似下面的转换将可以做到zero-copy零拷贝import pandas as pd import polars as pl df pd.DataFrame( { a: [one, two], b: [{name: Billy, age: 3}, {name: Bob, age: 4}], } ) pl.from_pandas(df)同时使用多个 dataframe 库的用户将能更轻松地在它们之间切换。五、未来收益让每个 dtype 都有 PyArrow 等价物5.1 用户侧全面摆脱object要求 PyArrow 将简化 pandas 内部相关开发并潜在改善更适合由 PyArrow 承担的功能包括在构造函数或索引操作期间避免运行时检查 PyArrow 是否可用来执行 PyArrow 对象推断尽可能规避 NumPyobjectdtype所有存在 PyArrow 等价物的 dtype 都会被自动推断为 Arrow 类型覆盖范围包括decimalbinary嵌套类型list 或 dict 数据字符串stringstimedate5.2 开发者侧砍掉冗余功能对 pandas 自身开发而言简化 PyArrow 支撑数据类型的开发——不再需要遍布各处的可选依赖检查潜在移除冗余功能包括read_parquet中的 fastparquet 引擎潜在的read_csv逻辑简化需更多调研factorizationdatetime/timezone 运算。六、代价与权衡DrawbacksPDEP-10 对反面意见同样开诚布公安装体积显著增加以 pip wheel 安装为例pandas NumPy 约需70MB而加入 PyArrow 需再增加约120MB。对 AWS Lambda 这类空间受限的开发/部署环境会产生负面影响。无 wheel 环境需要从源码构建在无法通过pip install或conda install获取 wheel 的环境中用户安装 pandas 时还需自行构建 Arrow C 及其依赖典型场景包括Alpine Linux常被用作 Docker 容器基础镜像Python 开发版未发布的 Python 版本。发布节奏耦合pandas 的开发和发布需要关注 PyArrow 的发布节奏。例如pandas 支持某个新发布的 Python 版本时需要先确认 PyArrow 是否已为该 Python 版本提供 wheel才能发布新的 pandas 版本。七、FAQ默认推断的边界到底在哪Q1为什么不用 NumPy 的 string 和 void 数据类型而非得用 PyArrowNumPy 字符串尚不可用而 PyArrow 字符串已经就绪NumPy 的voiddtype 与 PyArrow 的struct语义不同无法带来与其他 Arrow 系 dataframe 库相同的互操作性收益。Q2所有 PyArrow dtype 都准备好了吗现在设为默认是不是太早PDEP-10 明确回应到 3.0 它们大概率已就绪但并不会全部设为默认。例如pd.Series([1, 2, 3])仍会被自动推断为np.int64。默认推断只会改变那些当前没有 NumPy 等价物、且以objectdtype 存储的类型——例如字符串和嵌套数据类型。这一边界至关重要它保证了数值数据的行为不发生任何变化迁移冲击面被控制在最小范围。八、源码落地验证当前仓库中的实现证据PDEP-10 是设计文档其结论需要在代码中兑现。对照当前仓库源码可以从三个层面看到这条演进路线的实际落地情况8.1 最低版本策略的演进7 → 16PDEP-10 原始提案规定 pandas 3.0 的 PyArrow 最低版本为 7。而在当前仓库中可选依赖版本清单 pandas/compat/_optional.py 记录的pyarrow最低版本已是16.0.0说明随着 PyArrow 自身的迭代最低版本要求已按至少发布 2 年的策略持续抬升。该版本在 pyproject.toml 中同样有约束pyarrow [pyarrow16.0.0]作为主 extra 出现而parquet、feather两个 extra 则要求pyarrow13.0.0。8.2future.infer_string选项从 opt-in 到默认PDEP-14 进一步落实了字符串 dtype 的默认化路径在 pandas 2.x 时代用户需显式开启pd.options.future.infer_string True来预览未来行为。而在当前仓库 pandas/core/config_init.py 中该选项的注册信息已经变为legacyFalse、defaultTrue、upcomingTrue文档字符串明确写着自 pandas 3.0 起将字符串序列推断为 str dtype 而非 object dtype 已成为默认行为该选项已被Pandas4Warning标记为弃用并注明将在 pandas 4.0 移除届时 str dtype 将始终被推断。这正好印证了 PDEP-10 → PDEP-14 的接力pandas 3.0 中字符串推断默认开启且不可回退。8.3StringDtype的 storage 与 na_value 双维度当前 pandas/core/arrays/string_.py 中的StringDtype实现了 PDEP-14 提出的命名方案storage参数python或pyarrow决定底层存储na_value参数np.nan或pd.NA区分缺失值语义。这保证了装没装 PyArrow都能提供行为一致的字符串 dtype——正是 PDEP-10 关于硬依赖被推迟后留下的 fallback 设计。8.4 构造与 I/O 层面的 PyArrow 推断在 pandas/core/dtypes/cast.py 中dtype_backend参数支持numpy_nullable与pyarrow两种取值当指定pyarrow时推断逻辑会通过to_pyarrow_type将基础 dtype 映射为对应的 Arrow 类型如ArrowDtype(pa.string())见 pandas/_libs/parsers.pyx。这正是 PDEP-10 所描述每个有 PyArrow 等价物的 dtype 都被推断为 Arrow 类型在解析器层面的实现雏形。九、与 PDEP-14 的演进关系从硬依赖到默认启用了解完 PDEP-10 后有必要厘清它与后续提案的关系避免产生版本认知偏差**PDEP-10本文主题**主张 PyArrow 成为硬依赖并默认推断string[pyarrow]**PDEP-14web/pandas/pdeps/0014-string-dtype.md**在社区反馈安装复杂度、体积与 NumPy 2.0 原生字符串类型出现的新背景下将方案修正为pandas 3.0 启用名为str的默认字符串 dtype优先使用 PyArrow若已安装否则回退到基于 NumPy object 的等价实现缺失值语义与其余默认 dtype 保持一致使用NaN。因此站在 pandas 3.0 的视角最准确的表述是字符串默认推断为专用 str dtype装了 PyArrow 就用 PyArrow 加速没装也有功能等价的回退路径。PyArrow 的实际角色从强制依赖演进为默认推荐依赖。十、结语PDEP-10 是一份兼具技术深度与生态视野的设计文档它以性能实测字符串方法最高约 12 倍提速论证了 PyArrow 字符串对用户的即时价值以嵌套类型推断与零拷贝互操作展望了更长远的收益同时也坦诚量化了安装体积、源码构建与发布节奏三大代价。虽然硬依赖最终被推迟但它的核心目标——让 pandas 3.0 默认使用 PyArrow 支撑的高效字符串 dtype——已在后续 PDEP-14 与当前仓库源码中兑现。对于 pandas 用户而言现在就可以通过pd.options.future.infer_string True提前验证 3.0 行为并在升级到 3.0 后享受strdtype 带来的性能与互操作性红利。【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价