NumPy 排序、条件筛选函数
在 NumPy 中,排序函数和条件筛选函数是处理 ndarray
(N 维数组)的关键工具,用于对数组元素进行排序或根据条件筛选数据。这些函数支持向量化操作,高效处理大规模数据,广泛应用于数据分析、预处理和机器学习。以下是对 NumPy 排序和条件筛选函数的详细中文讲解,涵盖定义、常用函数、示例、注意事项及最佳实践,帮助你全面掌握其用法。
一、NumPy 排序与条件筛选函数概述
1. 什么是排序和条件筛选函数?
- 排序函数:
- 定义:对数组元素按升序或降序排列,支持按轴排序。
- 用途:数据整理、排名、查找极值索引。
- 条件筛选函数:
- 定义:根据条件(如布尔表达式)从数组中提取或修改符合条件的元素。
- 用途:数据过滤、异常值处理、特征选择。
- 特点:
- 向量化:支持数组操作,无需显式循环。
- 高效性:基于 C 实现,性能优于 Python 原生操作。
- 多维支持:可按特定轴操作,适合多维数组。
2. 排序与条件筛选 vs Python 内置方法
特性 | NumPy 函数 | Python 内置方法 |
---|---|---|
输入类型 | 数组(标量、向量、矩阵) | 列表 |
向量化 | 支持数组操作 | 需循环处理 |
多维支持 | 按轴排序/筛选 | 不支持多维 |
性能 | 高效(C 实现) | 较慢(Python 实现) |
二、NumPy 排序函数
NumPy 提供了多种排序函数,支持对整个数组或特定轴排序,并返回排序结果或索引。
1. 基本排序函数
函数 | 描述 | 示例(标量) |
---|---|---|
np.sort(arr, axis=-1, kind='quicksort') | 返回排序后的数组 | sort([3, 1, 2]) = [1, 2, 3] |
np.argsort(arr, axis=-1) | 返回排序索引 | argsort([3, 1, 2]) = [1, 2, 0] |
np.partition(arr, kth, axis=-1) | 部分排序,前 kth 元素有序 | partition([3, 1, 2], 1) = [1, 2, 3] |
np.argpartition(arr, kth, axis=-1) | 返回部分排序索引 | argpartition([3, 1, 2], 1) = [1, 2, 0] |
- 语法:
np.sort(arr, axis=-1, kind='quicksort', order=None)
arr
:输入数组。axis
:排序轴(默认-1
,最后一维;None
展平排序)。kind
:排序算法(quicksort
、mergesort
、heapsort
)。order
:结构化数组的排序字段。
(1) np.sort
- 描述:返回排序后的数组副本,原数组不变。
- 示例:
import numpy as np
arr = np.array([3, 1, 2])
sorted_arr = np.sort(arr)
print(sorted_arr) # 输出:[1 2 3]
print(arr) # 输出:[3 1 2](原数组不变)
- 多维排序:
arr = np.array([[3, 1], [4, 2]])
print(np.sort(arr, axis=1)) # 按行排序
# 输出:
# [[1 3]
# [2 4]]
print(np.sort(arr, axis=0)) # 按列排序
# 输出:
# [[3 1]
# [4 2]]
(2) np.argsort
- 描述:返回排序后的索引。
- 示例:
arr = np.array([3, 1, 2])
indices = np.argsort(arr)
print(indices) # 输出:[1 2 0]
print(arr[indices]) # 输出:[1 2 3]
(3) np.partition
和 np.argpartition
- 描述:部分排序,仅确保第 kth 元素在正确位置,前后部分无需完全排序。
- 示例:
arr = np.array([3, 4, 1, 2])
print(np.partition(arr, 2)) # 输出:[1 2 3 4](前 2 个最小)
print(np.argpartition(arr, 2)) # 输出:[2 3 0 1]
2. 原地排序
- 函数:
arr.sort(axis=-1, kind='quicksort')
- 描述:直接修改原数组。
- 示例:
arr = np.array([3, 1, 2])
arr.sort()
print(arr) # 输出:[1 2 3]
三、NumPy 条件筛选函数
条件筛选函数用于根据布尔条件提取或修改数组元素,通常结合布尔索引或专用函数。
1. 布尔索引
- 描述:使用布尔数组筛选符合条件的元素。
- 示例:
arr = np.array([1, 2, 3, 4])
mask = arr > 2
print(mask) # 输出:[False False True True]
print(arr[mask]) # 输出:[3 4]
- 条件组合:
mask = (arr > 1) & (arr < 4)
print(arr[mask]) # 输出:[2 3]
2. 专用筛选函数
函数 | 描述 | 示例 |
---|---|---|
np.where(condition, x, y) | 根据条件选择元素 | where([True, False], [1, 2], [3, 4]) = [1, 4] |
np.nonzero(arr) | 返回非零元素索引 | nonzero([0, 1, 0]) = (array([1]),) |
np.extract(condition, arr) | 提取符合条件的元素 | extract([True, False, True], [1, 2, 3]) = [1, 3] |
np.select(condlist, choicelist) | 多条件选择 | select([[x>2], [x<2]], [1, 2], x) = [2, 2, 1] |
(1) np.where
- 描述:根据条件选择
x
或y
的元素,或返回条件为真的索引。 - 示例:
arr = np.array([1, 2, 3, 4])
print(np.where(arr > 2, arr, 0)) # 输出:[0 0 3 4]
print(np.where(arr > 2)) # 输出:(array([2, 3]),)
(2) np.nonzero
- 描述:返回非零(或条件为真)元素的索引。
- 示例:
arr = np.array([0, 1, 0, 2])
print(np.nonzero(arr)) # 输出:(array([1, 3]),)
(3) np.extract
- 描述:提取符合条件的元素。
- 示例:
arr = np.array([1, 2, 3, 4])
condition = arr > 2
print(np.extract(condition, arr)) # 输出:[3 4]
(4) np.select
- 描述:根据多个条件选择值。
- 示例:
arr = np.array([1, 2, 3])
condlist = [arr > 2, arr < 2]
choicelist = [10, 20]
print(np.select(condlist, choicelist, default=0)) # 输出:[20 0 10]
四、实际应用场景
1. 数据排序
按列排序并提取前 k 个元素:
arr = np.array([[3, 1], [4, 2]])
sorted_arr = np.sort(arr, axis=0) # 按列排序
print(sorted_arr) # 输出:[[3 1] [4 2]]
2. 异常值处理
替换超出范围的值:
arr = np.array([1, 2, 10, 4])
print(np.where(arr > 5, np.mean(arr), arr)) # 输出:[1. 2. 4.25 4.]
3. 排名计算
获取元素排序后的排名:
arr = np.array([3, 1, 2])
indices = np.argsort(arr)
print(indices) # 输出:[1 2 0]
4. 数据筛选
筛选符合条件的行:
arr = np.array([[1, 2], [3, 4], [5, 6]])
mask = arr[:, 0] > 2
print(arr[mask]) # 输出:[[3 4] [5 6]]
五、注意事项
- 排序副本 vs 原地:
np.sort
返回副本,原数组不变;arr.sort()
修改原数组:python arr = np.array([3, 1, 2]) print(np.sort(arr)) # 输出:[1 2 3] print(arr) # 输出:[3 1 2]
- 布尔索引副本:
- 布尔索引返回副本,修改不影响原数组:
python arr = np.array([1, 2, 3]) subset = arr[arr > 1] subset[0] = 10 print(arr) # 输出:[1 2 3]
- 轴指定:
- 排序或筛选时明确轴以避免混淆:
python arr = np.array([[1, 2], [3, 4]]) print(np.sort(arr, axis=0)) # 按列排序
- 性能优化:
- 部分排序(
np.partition
)比全排序快:python arr = np.array([3, 1, 2, 4]) print(np.partition(arr, 2)) # 更快
- 空数组:
- 空数组可能导致错误:
python arr = np.array([]) # np.sort(arr) # 无问题,但需检查结果
六、最佳实践
- 优先向量化:
- 使用 NumPy 函数避免循环:
python arr = np.array([3, 1, 2]) print(np.sort(arr)) # 高效
- 明确轴指定:
- 确保轴与需求一致:
python arr = np.array([[1, 2], [3, 4]]) print(np.sort(arr, axis=1))
- 优化部分排序:
- 使用
np.partition
获取前 k 个元素:python print(np.partition(arr, 1, axis=1))
- 检查条件形状:
- 布尔索引形状需匹配:
python mask = arr[:, 0] > 2 print(mask.shape, arr.shape)
- 结合其他库:
- 与 Pandas 集成:
python import pandas as pd df = pd.DataFrame(arr) print(df.sort_values(by=0))
- 调试输出:
- 控制显示精度:
python np.set_printoptions(precision=2)
七、总结
NumPy 的排序函数(如 sort
、argsort
、partition
)和条件筛选函数(如 where
、nonzero
、extract
)提供了高效的数组排序和数据筛选功能。排序支持按轴操作,筛选支持布尔索引和多条件选择。掌握这些函数,理解副本与原地操作、轴指定和性能优化,结合最佳实践(如向量化、检查形状),能高效完成数据处理任务。
如果你需要更复杂的排序或筛选示例(如多维排序、性能优化)或特定场景的代码,请告诉我!