pin_drop当前位置:知识文库 ❯ 图文

NumPy数组排序详解 - sort/argsort/partition

一、概述

NumPy提供了多种排序函数,支持沿指定轴排序、部分排序、稳定排序等。np.sort()返回排序后的副本,np.argsort()返回排序索引,np.partition()用于部分排序(如找前K个最小值)。

理解不同排序函数的特点和参数,可以在不同场景下选择最优方案。例如Top-K问题使用partition比全排序效率更高。


二、语法与常用函数

代码示例

np.sort(a, axis=-1, kind='quicksort')
np.argsort(a, axis=-1, kind='quicksort')
np.partition(a, kth, axis=-1)
np.argpartition(a, kth, axis=-1)
np.searchsorted(a, v)
arr.sort()  # 原地排序

三、参数说明

np.sort参数

参数 类型 默认值 说明
a array_like 必填 要排序的数组
axis int/None -1 排序轴,None为展平排序
kind str 'quicksort' 排序算法
order str/list None 结构化数组的排序字段

排序算法

算法 kind值 速度 稳定性 说明
快速排序 'quicksort' 最快 不稳定 默认算法
归并排序 'mergesort' 中等 稳定 保持相等元素顺序
堆排序 'heapsort' 较慢 不稳定 内存效率高
基数排序 'stable' 中等 稳定 自动选择稳定算法

四、基本排序

np.sort()返回排序后的数组副本,不修改原数组。arr.sort()原地排序,直接修改原数组。

代码示例

import numpy as np

arr = np.array([42, 15, 8, 23, 16, 4, 31])

# np.sort:返回排序副本
sorted_arr = np.sort(arr)
print(f"原数组: {arr}")
print(f"排序后: {sorted_arr}")

# 降序排序
sorted_desc = np.sort(arr)[::-1]
print(f"降序: {sorted_desc}")

# 原地排序
arr2 = np.array([42, 15, 8, 23, 16])
arr2.sort()
print(f"原地排序: {arr2}")

输出结果:

代码示例

原数组: [42 15  8 23 16  4 31]
排序后: [ 4  8 15 16 23 31 42]
降序: [42 31 23 16 15  8  4]
原地排序: [ 8 15 16 23 42]

五、多维数组排序与argsort

多维数组排序可通过axis参数指定排序方向。axis=0沿列排序,axis=1沿行排序,axis=None展平后排序。argsort()返回排序后的索引数组,可用于对关联数组进行同步排序。

代码示例

import numpy as np

arr = np.array([[3, 1, 4], [1, 5, 9], [2, 6, 5]])
print(f"原数组:\n{arr}")

# 沿行排序(每行内部排序)
print(f"\naxis=1(每行排序):\n{np.sort(arr, axis=1)}")

# 沿列排序(每列内部排序)
print(f"\naxis=0(每列排序):\n{np.sort(arr, axis=0)}")

# 展平排序
print(f"\n展平排序: {np.sort(arr, axis=None)}")

# argsort:获取排序索引
arr1d = np.array([30, 10, 20])
indices = np.argsort(arr1d)
print(f"\n原数组: {arr1d}")
print(f"排序索引: {indices}")
print(f"通过索引排序: {arr1d[indices]}")

输出结果:

代码示例

原数组:
[[3 1 4]
 [1 5 9]
 [2 6 5]]

axis=1(每行排序):
[[1 3 4]
 [1 5 9]
 [2 5 6]]

axis=0(每列排序):
[[1 1 4]
 [2 5 5]
 [3 6 9]]

展平排序: [1 1 2 3 4 5 5 6 9]

原数组: [30 10 20]
排序索引: [1 2 0]
通过索引排序: [10 20 30]

六、部分排序与搜索

partition()只保证第k个位置是正确的,前k个元素小于等于第k个,后面的元素大于等于第k个,但不保证有序。这种方式时间复杂度为O(n),比全排序O(n log n)更快,适合Top-K问题。

代码示例

import numpy as np

arr = np.array([42, 15, 8, 23, 16, 4, 31, 5, 19, 34])

# partition:找前3个最小值(不保证顺序)
part = np.partition(arr, 3)
print(f"原数组: {arr}")
print(f"partition(3): {part}")
print(f"前3个最小值: {sorted(part[:3])}")

# argpartition:找前3个最小值的索引
indices = np.argpartition(arr, 3)
print(f"前3个最小值索引: {indices[:3]}")
print(f"前3个最小值: {arr[indices[:3]]}")

# searchsorted:在已排序数组中查找插入位置
sorted_arr = np.sort(arr)
values = [10, 25, 40]
positions = np.searchsorted(sorted_arr, values)
print(f"\n已排序数组: {sorted_arr}")
print(f"查找值: {values}")
print(f"插入位置: {positions}")

输出结果:

代码示例

原数组: [42 15  8 23 16  4 31  5 19 34]
partition(3): [ 4  5  8 15 16 23 31 42 19 34]
前3个最小值: [4, 5, 8]
前3个最小值索引: [5 7 2]
前3个最小值: [4 5 8]

已排序数组: [ 4  5  8 15 16 19 23 31 34 42]
查找值: [10, 25, 40]
插入位置: [3 7 9]

小贴士

searchsorted基于二分查找实现,要求输入数组必须是已排序的。side='left'返回第一个大于等于插入值的位置,side='right'返回第一个大于插入值的位置,默认为'left'。


七、实际应用场景

  • 场景1:数据分析中,使用sort对数据排序,使用argsort获取排名,如对成绩排序后获取学生排名

  • 场景2:推荐系统中,使用argpartition找Top-K推荐项,避免全量排序,大幅提升性能

  • 场景3:搜索算法中,使用searchsorted在有序数组中快速查找插入位置,时间复杂度O(log n)


八、注意事项

注意:np.sort()返回副本不修改原数组,arr.sort()原地排序修改原数组。根据是否需要保留原始数据选择使用。

注意:partition只保证第k个位置是正确的,前k个和后面的元素不保证有序。如果需要有序的前k个元素,需要对partition结果的前k个再次排序。

注意:searchsorted要求输入数组必须是已排序的,否则结果无意义。使用前务必确认数组已排序。


九、排序函数对比

函数 返回值 是否原地 时间复杂度 适用场景
np.sort() 排序副本 O(n log n) 完整排序
arr.sort() None O(n log n) 原地排序
np.argsort() 索引数组 O(n log n) 获取排名
np.partition() 部分排序副本 O(n) Top-K问题
np.argpartition() 索引数组 O(n) Top-K索引
np.searchsorted() 位置索引 O(log n) 二分查找

十、练习题

练习1

创建一个包含20个随机整数的数组,分别使用np.sort()和arr.sort()排序,验证前者不修改原数组

练习2

创建一个学生成绩数组,使用argsort获取排名,并按排名输出学生姓名和成绩

练习3

创建一个包含1000个随机数的数组,使用partition找出前10个最小值,对比与全排序的性能差异

常见问题

np.sort()和arr.sort()有什么区别?

np.sort()返回排序后的副本,原数组不变;arr.sort()原地排序,直接修改原数组。如果后续还需要原始数据,使用np.sort();如果不需要原始数据且要节省内存,使用arr.sort()。

partition和sort哪个更快?

当只需要前K个最小值或最大值时,partition的时间复杂度是O(n),sort是O(n log n)。数据量越大,partition的性能优势越明显。但如果需要完整排序,只能使用sort。

什么是排序稳定性?为什么它重要?

稳定排序保证相等元素的相对顺序不变。例如按成绩排序后,相同成绩的学生保持原来的先后顺序。这在多级排序中很重要,如先按学号排序再按成绩排序。

argsort如何实现多列排序?

对于多维数据排序,可以使用lexsort函数实现多列排序。lexsort从最后一个键开始排序,优先级从右到左递减。例如先按成绩降序,成绩相同按学号升序。

标签: NumPy 数组排序 argsort partition Top-K searchsorted

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: NumPy文件读写完整指南 - npy/npz/CSV格式 下一篇: NumPy数组拼接与分割 - concatenate/stack/split

poll相关推荐