)
pandas 数据排序指南用 DataFrame.sort_values 实现多列排序与跨工具对照R/SAS/Stata/Excel【免费下载链接】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/pandasDataFrame.sort_values是 pandas 中最常用的行排序入口它接收一个或多个列名组成的列表按列值对整张表进行稳定、可定制、可复现的排序。本文以官方文档 sorting.rst 为核心骨架结合 R 的arrange、SAS 的PROC SORT、Stata 的sort与 Excel 排序对话框做横向对照并深入 pandas/core/frame.py 源码展开每个参数的底层行为。读完本文你将掌握多列排序、混合升降序、缺失值位置控制、自定义排序键等完整实战能力。一、这个排序片段讲的是什么在 pandas 官方文档的入门指南Getting started中有一个专门用于与其他工具对比的公共片段位于 doc/source/getting_started/comparison/includes/sorting.rst全文核心只有一句话pandas has aDataFrame.sort_valuesmethod, which takes a list of columns to sort by.即pandas 通过DataFrame.sort_values完成按值排序且它接收一个列名列表来指定排序依据。配套示例使用经典的小费数据集tipstips tips.sort_values([sex, total_bill]) tips这个片段通过 RST 的.. include::指令被四篇对比文档复用因此它实际承载了四套工具的排序语义对照对比页面对应工具的排序写法与 pandas 的对应关系comparison_with_r.rstR 的arrange(df, col1, col2)df.sort_values([col1, col2])comparison_with_sas.rstSAS 的proc sort datatips; by sex total_bill; run;按[sex, total_bill]多列排序comparison_with_stata.rstStata 的sort sex total_bill同上comparison_with_spreadsheets.rstExcel 排序对话框先按sex再按total_bill同上可以看到无论是arrange(df, col1, col2)、by sex total_bill还是 Excel 的多级排序先按第一个键、再按第二个键的字典序lexicographic语义在 pandas 中统一收敛为sort_values传入列名列表。这正是官方专门抽出这个 include 片段的原因多列排序是所有工具用户迁移到 pandas 时最常用的操作之一。二、核心用法单列与多列排序2.1 按单个列排序最基础的形式是传入一个列名字符串df.sort_values(bytotal_bill)结果是一个新的 DataFrame行按total_bill的取值从小到大排列原数据不会被修改。2.2 按多个列排序官方示例当传入列名列表时pandas 执行多键字典序排序先按列表中第一个键排序在第一个键取值相等的行内部再按第二个键排序依次类推。官方 include 片段中的示例tips tips.sort_values([sex, total_bill])等价于 R 的arrange(tips, sex, total_bill)、SAS 的by sex total_bill、Stata 的sort sex total_bill以及 Excel 中先按 sex 排序再按 total_bill 排序的多级排序设置。在 pandas/core/frame.py 的 docstring 中多列排序的语义被明确表述为行先按col1排序然后在col1取值相同的行内按col2排序。 df pd.DataFrame( ... { ... col1: [A, A, B, np.nan, D, C], ... col2: [2, 1, 9, 8, 7, 4], ... col3: [0, 1, 9, 4, 2, 3], ... col4: [a, B, c, D, e, F], ... } ... ) df.sort_values(by[col1, col2]) col1 col2 col3 col4 1 A 1 1 B 0 A 2 0 a 2 B 9 9 c 5 C 4 3 F 4 D 7 2 e 3 NaN 8 4 D2.3by参数还可以排序索引层级by不局限于普通列名。从源码签名pandas/core/frame.py看当axis0默认按行方向排序时by可以包含索引层级index levels和/或列标签当axis1按列方向排序时by可以包含列层级和/或索引标签。这意味着多级索引MultiIndex的数据也可以直接按层级名排序。三、完整参数解析对照源码DataFrame.sort_values的完整签名如下见 pandas/core/frame.pydef sort_values( self, by: IndexLabel, *, axis: Axis 0, ascending: bool | list[bool] | tuple[bool, ...] True, inplace: bool | lib.NoDefault lib.no_default, kind: SortKind quicksort, na_position: str last, ignore_index: bool False, key: ValueKeyFunc | None None, ) - DataFrame | None:各参数行为如下参数默认值说明by必填排序依据字符串或字符串列表axis0时可含索引层级与列标签axis0index排序方向也可传1columns按行标签/索引值排序各列ascendingTrue布尔值或与by等长的布尔列表用于混合升降序inplaceFalse是否原地修改自 3.1.0 起已废弃见 PDEP-8未来版本将移除kindquicksort排序算法quicksort、mergesort、heapsort、stableDataFrame 仅在按单列排序时生效na_positionlast缺失值放置位置first或lastignore_indexFalse为True时结果索引重置为0, 1, …, n-1keyNone排序前作用于每个排序键的可调用对象须为向量化函数3.1 混合升降序ascending传入与by等长的列表即可实现第一列升序、第二列降序的混合排序。官方 R 对比文档中arrange(df, desc(col1))对应df.sort_values(col1, ascendingFalse)多列场景则是tips.sort_values([sex, total_bill], ascending[True, False])源码会在len(by) ! len(ascending)时抛出ValueError见 pandas/core/frame.py保证两个列表严格一一对应。3.2 缺失值NA的位置控制na_position控制 NaN / NaT 等缺失值落在排序结果的哪一端默认last df.sort_values(bycol1, ascendingFalse) col1 col2 col3 col4 4 D 7 2 e 5 C 4 3 F 2 B 9 9 c 0 A 2 0 a 1 A 1 1 B 3 NaN 8 4 D df.sort_values(bycol1, ascendingFalse, na_positionfirst) col1 col2 col3 col4 3 NaN 8 4 D 4 D 7 2 e 5 C 4 3 F 2 B 9 9 c 0 A 2 0 a 1 A 1 1 B注意无论ascending取何值na_position都是独立控制的——这正是它在多列排序下容易踩坑的地方每一列的 NA 都会按同一规则聚到对应端。3.3 自定义排序键keykey参数让排序键先经过一次向量化变换再比较例如忽略大小写的字符串排序官方 docstring 示例见 pandas/core/frame.py df.sort_values(bycol4, keylambda col: col.str.lower()) col1 col2 col3 col4 0 A 2 0 a 1 A 1 1 B 2 B 9 9 c 3 NaN 8 4 D 4 D 7 2 e 5 C 4 3 Fkey函数必须满足三条约束源码 docstring见 pandas/core/frame.py向量化接收一个Series返回与输入同形状的Series与内置sorted的key类似但作用于整列而非单个元素对by中的每一列独立应用。典型的进阶用法是自然排序natural sort例如把0hr, 128hr, 64hr按数值语义而非字典序排列可使用natsort包的natsort_keygen() from natsort import natsort_keygen df.sort_values(by[hours, mins], keynatsort_keygen()) hours mins value 0 0hr 10mins 10 2 0hr 40mins 30 4 64hr 10mins 50 3 64hr 40mins 40 5 128hr 10mins 60 1 128hr 40mins 203.4 排序算法kindkind可选quicksort、mergesort、heapsort、stable对应 NumPy 的排序算法。其中mergesort与stable是稳定排序能保持相等键之间的原始相对顺序。需要强调的是对于 DataFramekind仅在按单个列或单个标签排序时生效——多列排序内部走的是字典序索引器lexsort_indexer不接收kind参数。3.5ignore_index与废弃的inplaceignore_indexTrue会把结果索引重设为0, 1, …, n-1适合排序后无需保留原始行号、随后要与其他数据拼接的场景inplaceTrue自 pandas 3.1.0 起已废弃源码中以Pandas4Warning提示见 pandas/core/frame.py将在 pandas 4.0 移除依据是 PDEP-8 In-place methods in pandas。官方推荐直接使用返回新对象的写法避免原地修改带来的视图/拷贝语义混乱。四、源码级实现原理多列与单列走两条路径阅读 pandas/core/frame.py 的实现可以发现sort_values内部按by的长度分成了两条路径路径一多列排序len(by) 1keys (self._get_label_or_level_values(x, axisaxis) for x in by) ... indexer lexsort_indexer(keys_data, ordersascending, na_positionna_position, keykey)先将每个排序键提取为底层数组支持列标签或索引层级再交给pandas._libs.algos.lexsort_indexer做一次性的多键字典序排序ascending与na_position在这里以orders形式整体传入。这意味着多列排序没有逐列调用排序算法而是单次词法比较完成兼顾正确性与性能。路径二单列排序len(by) 1indexer nargsort(k, kindkind, ascendingascending, na_positionna_position, keykey)单列场景才使用nargsort此时kind参数才会被真正消费这也解释了 3.4 节中的限制。两条路径最终都会用算出的indexer对内部数据块管理器BlockManager执行self._mgr.take(indexer, ...)完成行的重排见 pandas/core/frame.py并通过__finalize__继承原对象的元数据。若索引恰好是天然有序的RangeIndex则会走浅拷贝的快速路径is_range_indexer分支避免无谓的取数开销。五、跨工具迁移对照速查整理自 comparison_with_r.rst 的快速参考表是迁移到 pandas 时最常用的两条规则R / 其他工具pandasarrange(df, col1, col2)/ SASby col1 col2/ Statasort col1 col2df.sort_values([col1, col2])arrange(df, desc(col1))/ SASdescendingdf.sort_values(col1, ascendingFalse)其余常用对照语义pandas 写法按索引/标签排序df.sort_index()Series 按值排序s.sort_values()先排序再取前 n 行df.sort_values(col).head(n)直接取 n 个最大/最小值df.nlargest(n, col)/df.nsmallest(n, col)关于多列排序中缺失值、重复键的顺序是否确定源码 docstring 给出的结论是对于给定输入排序结果是确定性的deterministic即同一数据多次排序会得到一致结果这为可复现的数据处理管线提供了保证。六、测试与验证pandas 仓库对sort_values有完善的单元测试覆盖主要位于 pandas/tests/frame/methods/test_sort_values.py覆盖以下维度单列/多列排序的正确性与稳定性ascending列表与by长度不匹配时的ValueErrorna_positionfirst/last对缺失值的处理kind各算法的等价性验证key函数含大小写不敏感、自然排序的行为ignore_index与inplace的语义。groupby场景下如组内排序、分组后取 top-n的测试散见于 pandas/tests/groupbySeries 的对应测试则在 pandas/tests/series 下。如果你希望验证本文中的示例可以在本地安装 pandas 后直接运行给出的代码片段若想了解lexsort_indexer与nargsort的底层实现可继续阅读 pandas/_libs/algos.pyx。七、小结围绕官方 include 片段 sorting.rst 的一句话核心——DataFrame.sort_values接收列名列表进行排序——本文完成了从四套工具语义对照、完整参数行为到源码实现路径的全面展开。掌握sort_values的多列字典序语义、混合升降序、na_position缺失值控制与向量化key函数即可覆盖日常 90% 以上的排序需求其单列走nargsort、多列走lexsort_indexer的双路径设计也解释了为何kind参数只在单列场景生效。这套能力与sort_index、nlargest/nsmallest组合使用足以构建完整、可复现的排序逻辑。【免费下载链接】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),仅供参考