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:排序算法(quicksortmergesortheapsort)。
  • 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.partitionnp.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

  • 描述:根据条件选择 xy 的元素,或返回条件为真的索引。
  • 示例
  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]]

五、注意事项

  1. 排序副本 vs 原地
  • np.sort 返回副本,原数组不变;arr.sort() 修改原数组:
    python arr = np.array([3, 1, 2]) print(np.sort(arr)) # 输出:[1 2 3] print(arr) # 输出:[3 1 2]
  1. 布尔索引副本
  • 布尔索引返回副本,修改不影响原数组:
    python arr = np.array([1, 2, 3]) subset = arr[arr > 1] subset[0] = 10 print(arr) # 输出:[1 2 3]
  1. 轴指定
  • 排序或筛选时明确轴以避免混淆:
    python arr = np.array([[1, 2], [3, 4]]) print(np.sort(arr, axis=0)) # 按列排序
  1. 性能优化
  • 部分排序(np.partition)比全排序快:
    python arr = np.array([3, 1, 2, 4]) print(np.partition(arr, 2)) # 更快
  1. 空数组
  • 空数组可能导致错误:
    python arr = np.array([]) # np.sort(arr) # 无问题,但需检查结果

六、最佳实践

  1. 优先向量化
  • 使用 NumPy 函数避免循环:
    python arr = np.array([3, 1, 2]) print(np.sort(arr)) # 高效
  1. 明确轴指定
  • 确保轴与需求一致:
    python arr = np.array([[1, 2], [3, 4]]) print(np.sort(arr, axis=1))
  1. 优化部分排序
  • 使用 np.partition 获取前 k 个元素:
    python print(np.partition(arr, 1, axis=1))
  1. 检查条件形状
  • 布尔索引形状需匹配:
    python mask = arr[:, 0] > 2 print(mask.shape, arr.shape)
  1. 结合其他库
  • 与 Pandas 集成:
    python import pandas as pd df = pd.DataFrame(arr) print(df.sort_values(by=0))
  1. 调试输出
  • 控制显示精度:
    python np.set_printoptions(precision=2)

七、总结

NumPy 的排序函数(如 sortargsortpartition)和条件筛选函数(如 wherenonzeroextract)提供了高效的数组排序和数据筛选功能。排序支持按轴操作,筛选支持布尔索引和多条件选择。掌握这些函数,理解副本与原地操作、轴指定和性能优化,结合最佳实践(如向量化、检查形状),能高效完成数据处理任务。

如果你需要更复杂的排序或筛选示例(如多维排序、性能优化)或特定场景的代码,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注