pandas 1.0 里程碑解读:缺失值统一、StringDtype 与版本治理策略
【免费下载链接】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
2020 年 1 月 29 日,pandas 正式发布 1.0.0。这既是一次普通的功能版本迭代,也是项目十余年发展历程中的一座象征性里程碑。本文以官方博客 pandas-1.0.md 为主线,结合仓库中完整的 v1.0.0 发布说明,为你梳理 1.0 版本的技术内核——实验性的pd.NA缺失值标量、全新string字符串类型、可空布尔类型、以及面向未来的新弃用策略,并回顾这个版本背后的社区与治理变革。
一、为什么 1.0 是一个里程碑
从碎片化生态到事实标准
pandas 起步于 2011 年,彼时科学 Python 生态处于碎片化状态:统计学与数据科学领域还没有一个标准的、富语义的(rich)数据结构。这与 NumPy 当年整合各色数组实现的历史如出一辙。在随后的岁月里,pandas 逐渐成为 Python 数据科学生态的de facto(事实上)标准——既被数据科学家和分析师直接使用,也被大量上层库当作基础数据结构来构建。
官方博客明确指出,如今整个生态正处于新一轮的探索期:多种新的 DataFrame 实现相继出现,以填补 pandas 尚未覆盖的需求。pandas 团队正与这些项目协作,共同确立富数据结构的共享标准与语义(参见 2019 年 EuroSciPy 的 DataFrame Summit 相关工作)。
"1.0" 的象征意义
值得注意的是,1.0.0 发布时 pandas 代码库已近 12 年历史,因此"1.0.0"这个版本号更多是一种象征:它庆祝的是核心开发者团队与贡献者社区的成长。正如博客所言,几乎没有开源项目是真正"完成"的,pandas 亦然——团队承认 pandas 如今占据的关键地位,并打算继续演进,去适应全球数据工作者不断变化的需求。
二、版本治理变革:新的弃用策略
从 1.0.0 开始,pandas 采用 SemVer(语义化版本)的变体来管理版本发布,这是本版本最重要的流程性变化(详见 v1.0.0.rst "New deprecation policy" 一节):
- 弃用(deprecation)在次版本引入,例如 1.1.0、1.2.0、2.1.0;
- 弃用在主版本强制执行,例如 1.0.0、2.0.0、3.0.0;
- 破坏性 API 变更只发生在主版本(实验性功能除外)。
同时,官方强烈建议:在升级到 pandas 1.0 之前,先升级到 pandas 0.25,并确保代码在无警告的情况下运行。因为 1.0 版本移除了大量此前版本已弃用的功能(详见下文"破坏性变更"部分),直接跨越式升级可能带来大量报错。
三、实验性新特性:缺失值语义的统一
1.pd.NA:统一的缺失值标量
1.0 引入了一个新的单例值pd.NA,用于表示标量缺失值。此前 pandas 中缺失值表示方式十分混乱:
- 浮点数据用
np.nan; - object-dtype 数据用
np.nan或None; - 时间日期类数据用
pd.NaT。
pd.NA的目标是提供一个可以跨数据类型一致使用的"缺失"指示器,目前被可空整数类型、可空布尔类型以及新的字符串类型所使用。需要特别注意的是,该特性处于实验阶段,pd.NA的行为可能在没有警告的情况下发生变化。
>>> s = pd.Series([1, 2, None], dtype="Int64") >>> s 0 1 1 2 2 <NA> dtype: Int64 >>> s[2] <NA>与np.nan相比,pd.NA在部分运算中行为不同。除算术运算外,pd.NA在比较运算中也以"缺失/未知"的方式传播:
>>> np.nan > 1 False >>> pd.NA > 1 <NA>在逻辑运算中,pd.NA遵循三值逻辑(Kleene logic)规则:
>>> pd.NA | True Truepd.NA的实现定义在 Cython 层 pandas/_libs/missing.pyx(class NAType(C_NAType)与单例C_NA = NAType()),从源码结构可以推断,其运算语义(比较传播、逻辑三值化)均由底层的NAType对象统一承载,这正是它能跨类型保持一致"缺失"语义的机制基础。
2.string:专为字符串设计的 dtype
1.0 新增了StringDtype扩展类型。此前字符串通常存储在 object-dtype 的 NumPy 数组中,这带来三个问题(详见 v1.0.0.rst):
- object-dtype 数组可能意外混入字符串与非字符串,而
StringArray只能存字符串; - object-dtype 会破坏依赖 dtype 的操作(如
DataFrame.select_dtypes),无法干净地只选出文本列; - 阅读代码时,object-dtype 数组的内容不如
string直观。
用法如下,dtype=pd.StringDtype()与别名"string"等价:
>>> s = pd.Series(['abc', None, 'def'], dtype="string") >>> s 0 abc 1 <NA> 2 def dtype: string常规的字符串访问器方法照常工作,返回的 Series 或 DataFrame 列会保持 string dtype;返回整数的访问器方法则会返回Int64Dtype:
>>> s.str.upper() 0 ABC 1 <NA> 2 DEF dtype: string >>> s.str.split('b', expand=True).dtypes 0 string 1 string dtype: object >>> s.str.count("a") 0 1 1 <NA> 2 0官方建议在处理字符串时显式使用string数据类型。注意StringDtype目前同样被视为实验性,其实现与部分 API 可能在没有警告的情况下变化。
3.boolean:可存缺失值的布尔类型
BooleanDtype/BooleanArray是专为可容纳缺失值的布尔数据设计的扩展类型。默认基于 bool-dtype NumPy 数组的bool类型只能存True或False,无法表示缺失;而BooleanArray通过单独维护一个掩码(mask)来记录缺失值:
>>> pd.Series([True, False, None], dtype=pd.BooleanDtype()) 0 True 1 False 2 <NA> dtype: boolean同样可以使用别名"boolean"。
4.convert_dtypes:一键切换到扩展 dtype
为了推广支持pd.NA的扩展 dtype(StringDtype、BooleanDtype、Int64Dtype、Int32Dtype等),1.0 引入了DataFrame.convert_dtypes与Series.convert_dtypes方法:
>>> df = pd.DataFrame({'x': ['abc', None, 'def'], ... 'y': [1, 2, np.nan], ... 'z': [True, False, True]}) >>> df.dtypes x object y float64 z bool dtype: object >>> converted = df.convert_dtypes() >>> converted.dtypes x string y Int64 z boolean dtype: object这在用read_csv、read_excel等读取数据后尤其有用,可以一键把传统 dtype 转换到支持缺失值语义的扩展 dtype。
四、常规增强:性能与功能的双线推进
1. Numba 引擎驱动rolling.apply/expanding.apply
1.0 为Rolling.apply和Expanding.apply新增了engine关键字,允许用户改用 Numba 而非 Cython 来执行函数。当 apply 函数能作用于 numpy 数组、且数据集较大(约 100 万行以上)时,Numba 引擎可带来显著的性能提升。
2. 自定义滚动窗口:BaseIndexer
新增pandas.api.indexers.BaseIndexer类,允许用户自定义 rolling 操作中窗口边界的生成方式。用户可以在子类中实现自己的get_window_bounds方法,生成每次滚动聚合所用窗口的起止索引。
3.DataFrame.to_markdown:输出 Markdown 表格
>>> df = pd.DataFrame({"A": [1, 2, 3], "B": [1, 2, 3]}, index=['a', 'a', 'b']) >>> print(df.to_markdown()) | | A | B | |:---|----:|----:| | a | 1 | 1 | | a | 2 | 2 | | b | 3 | 3 |4. 其他值得关注的增强
DataFrame.to_string新增max_colwidth参数控制宽列截断;Series/Index/DataFrame.to_numpy新增na_value参数指定缺失值转换值;MultiIndex.from_product在未显式提供 names 时从输入推断层级名;DataFrame.to_json新增indent整数参数支持 JSON 美化输出;read_excel支持通过engine='pyxlsb'读取二进制 Excel(.xlsb)文件;DataFrame.sort_values、sort_index、drop_duplicates新增ignore_index关键字;read_json现在可解析NaN、Infinity和-Infinity;- 新增实验性的
DataFrame.attrs用于存放数据集的全局元数据; DataFrame.to_pickle与read_pickle现在接受 URL。
五、破坏性变更与旧功能移除(升级必读)
1.0 移除了一大批此前已弃用的功能,升级前务必对照检查:
- 移除
SparseSeries、SparseDataFrame及DataFrame.to_sparse:官方推荐改用带稀疏值的Series/DataFrame; - 移除
Series.ix与DataFrame.ix、Series.as_matrix/DataFrame.as_matrix、DataFrame.from_items、Series.ptp等一批老 API; - 移除
to_msgpack/read_msgpack; - 移除
DataFrame.get_value/set_value、Series.get_value/set_value; - Matplotlib 单元注册行为变更:pandas 不再因导入而副作用式注册 matplotlib 转换器,需要时显式设置
pd.options.plotting.matplotlib.register_converters = True(DataFrame.plot/Series.plot仍会自动注册); MultiIndex层级名重构:names 现在独立于 levels 存储,mi.levels[0].name = "new name"会抛出RuntimeError,须改用MultiIndex.set_names;DataFrame.rename只接受一个位置参数:同时传入mapper与index/columns会抛出TypeError,应改用df.rename(index={...}, columns={...});DataFrame.info输出升级:新增行号、Non-Null Count列与表格化格式;pd.array推断行为变化:字符串数据(含缺失值)返回StringArray,整数数据(含缺失值)返回IntegerArray,布尔数据(含缺失值)返回BooleanArray;IntegerArray改用pd.NA作为缺失值标记:np.asarray(a, dtype="float")会抛出ValueError,须用a.to_numpy(dtype="float", na_value=np.nan);Series(a).sum(skipna=False)返回<NA>而非nan;value_counts()返回可空整数 dtype;比较操作返回BooleanArray且缺失值会传播而非恒为不等;- 空
Series默认 dtype 警告:pd.Series()会发出DeprecationWarning,未来默认 dtype 将从float64改为object; Categorical.min默认返回最小值而非np.nan(skipna=True 时)。
版本与依赖门槛
pandas 1.0.0 要求Python 3.6.1 及以上。核心依赖最低版本:numpy 1.13.3、pytz 2015.4、python-dateutil 2.6.1(均为必需);可选依赖如 numba 0.46.0、pyarrow 0.13.0、openpyxl 2.5.7、fastparquet 0.3.2 等也有相应最低版本要求。构建方面,pandas 新增了pyproject.toml,且不再在 PyPI 源码发行版中包含 Cython 生成文件——从源码构建时无需再预先安装 Cython 即可执行pip install pandas。
性能改进一览
1.0 同步带来了大量性能优化,包括:DataFrame 与标量的算术/比较运算、非唯一IntervalIndex的索引、MultiIndex.is_monotonic、cut使用IntervalIndexbins、用range初始化 DataFrame、DataFrame.corr(method="spearman")、DataFrame.replace、向量化的select_dtypes、Index.equals/MultiIndex.equals等。
六、社区与项目健康:从志愿者到资金支持
1.0 发布周期是 pandas 首次获得任何形式的赠款资助。pandas 通过 CZI(Chan Zuckerberg Initiative)的Essential Open Source Software for Science(EOSS)计划获得资金支持。
pandas 项目长期以来高度依赖志愿者贡献;这些贡献由一部分获得雇主时间支持的核心维护者统筹(详见机构合作伙伴列表)。赠款中最大的工作项是库维护,具体包括与社区成员协作处理大量积压的开放 issue 与 pull request。此外,2019 年 pandas 还通过用户调查(约 1250 份有效回复,见 2019 用户调查博客)指导开发方向:调查显示"扩展到大规模数据集"是用户最关心的改进点,其次是内存效率(如原生字符串类型、减少内部拷贝)——这些诉求在 1.0 的stringdtype、Numba 引擎等特性中已初见端倪。
七、面向未来
1.0 只是新阶段的起点。项目的 路线图 列出了未来几年的发展方向,包括与生态中其他 DataFrame 实现协作确立共享标准等议题。对普通用户而言,最重要的行动是:
- 先升级到 0.25,清理代码中的所有弃用警告;
- 再升级到 1.0,享受统一的
pd.NA缺失值语义、string/boolean扩展类型与各项性能改进; - 迁移老代码时,重点排查
ix、as_matrix、from_items、SparseSeries等已移除 API,并将MultiIndex.labels替换为MultiIndex.codes。
完整的变更清单可查阅仓库内的 v1.0.0 发布说明,其中包含全部增强、API 变更、弃用、移除项、性能改进与数百条 bug 修复记录,是升级与代码迁移的权威参考。
【免费下载链接】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),仅供参考