Skip to content

排序、搜索和计数函数

NumPy 提供了一系列高效的函数用于数组排序、元素搜索和出现次数计数。

NumPy 提供了几种排序算法 (quicksort 快速排序, mergesort 归并排序, heapsort 堆排序, stable 稳定排序)。选择不同的算法会影响性能和 稳定性 (stable)(即相等元素的相对顺序是否保持不变)。

类型 (kind)平均速度最差情况工作空间稳定性 (Stable)
‘quicksort’ (默认)最快O(n^2)常量否
’mergesort’中等O(n*log(n))~n/2是
’heapsort’最慢O(n*log(n))常量否
’stable’中等O(n*log(n))~n/2是 (适配 mergesort/timsort)

注意: 当需要保留相等元素的原始顺序时,‘stable’ 通常是一个不错的选择。

返回数组的 排序副本。它不会修改原始数组。

numpy.sort(a, axis=-1, kind=None, order=None)

参数:

参数描述
a待排序的输入数组。
axis沿哪个轴进行排序。默认是 -1 (最后一个轴)。如果为 None,则在排序前将数组 展平 (flatten)。
kind排序算法 (‘quicksort’, ‘mergesort’, ‘heapsort’, ‘stable’)。默认取决于 NumPy 版本,通常是 ‘quicksort’。
order对于 结构化数组 (structured array),指定按哪个 字段 (field) 进行排序。

沿不同轴排序二维数组和排序结构化数组。

import numpy as np
# --- 基本排序 ---
a = np.array([[3, 7], [9, 1]])
print('Original array:')
print(a)
# 沿最后一个轴 (行) 排序 - 默认行为
print('\nSorted along axis=-1 (rows):')
print(np.sort(a))
# 沿轴 0 (列) 排序
print('\nSorted along axis=0 (columns):')
print(np.sort(a, axis=0))
# 排序展平后的数组
print('\nSorted flattened array:')
print(np.sort(a, axis=None))
# --- 结构化数组排序 ---
# 定义一个结构化数据类型
dt = np.dtype([('name', 'S10'), ('age', int)])
people = np.array([('Raju', 21), ('Anil', 25), ('Ravi', 17), ('Amar', 27)], dtype=dt)
print('\n\nOriginal structured array:')
print(people)
# 按 'name' 字段排序
print('\nSorted by name:')
print(np.sort(people, order='name'))
# 按 'age' 字段排序
print('\nSorted by age:')
print(np.sort(people, order='age'))

输出:

Original array:
[[3 7]
[9 1]]
Sorted along axis=-1 (rows):
[[3 7]
[1 9]]
Sorted along axis=0 (columns):
[[3 1]
[9 7]]
Sorted flattened array:
[1 3 7 9]
Original structured array:
[(b'Raju', 21) (b'Anil', 25) (b'Ravi', 17) (b'Amar', 27)]
Sorted by name:
[(b'Amar', 27) (b'Anil', 25) (b'Raju', 21) (b'Ravi', 17)]
Sorted by age:
[(b'Ravi', 17) (b'Raju', 21) (b'Anil', 25) (b'Amar', 27)]

注意: 要对数组进行 就地排序 (修改原始数组),请使用 ndarray.sort() 方法:a.sort()。

执行 间接排序 (indirect sort)。它不返回排序后的数组,而是返回能对原始数组进行排序的 索引。当需要根据一个数组的顺序来排序多个相关数组时,这非常有用。

找到数组的排序索引并用它们重构数组。

import numpy as np
x = np.array([30, 10, 20])
print('Original array:')
print(x)
print('\nIndices that would sort x:')
indices = np.argsort(x)
print(indices)
print('\nReconstruct sorted array using indices:')
print(x[indices]) # 使用索引进行 高级索引 (fancy indexing)

输出:

Original array:
[30 10 20]
Indices that would sort x:
[1 2 0]
Reconstruct sorted array using indices:
[10 20 30]

使用一系列 键 (key)(数组)执行 间接 稳定排序。它首先根据提供的 最后一个 键进行排序,然后使用倒数第二个键来 打破平局 (break ties),依此类推。返回基于这些键对数据进行排序所需的索引。

首先按部门 (‘dv’),然后按姓名 (‘nm’) 对姓名进行排序。

import numpy as np
# 数据数组 (用于排序的键)
names = np.array(['Raju', 'Anil', 'Ravi', 'Amar'])
divisions = np.array(['f.y.', 's.y.', 's.y.', 'f.y.'])
# 首先按姓名排序,然后按部门排序 (键按后到先的顺序提供)
# 因此,主要排序键是 'names',次要排序键是 'divisions'
indices = np.lexsort((divisions, names))
print('Indices from lexsort (sort by names, then divisions):')
print(indices)
print('\nUse indices to get sorted data:')
print([f'{names[i]}, {divisions[i]}' for i in indices])

输出:

Indices from lexsort (sort by names, then divisions):
[3 1 0 2]
Use indices to get sorted data:
['Amar, f.y.', 'Anil, s.y.', 'Raju, f.y.', 'Ravi, s.y.']

NumPy 提供了查找最大/最小值或满足特定 条件 (condition) 的元素的函数。

分别返回沿给定轴的最大和最小元素的 索引。如果数组被展平 (axis=None),则返回展平数组中的索引。

import numpy as np
a = np.array([
[30, 40, 70],
[80, 20, 10],
[50, 90, 60]
])
print('Original array:')
print(a)
# 最大元素的索引 (展平后)
print('\nIndex of max element (flattened):', np.argmax(a))
# 最大元素的值
print('Value of max element:', a.flat[np.argmax(a)])
# 沿轴 0 (列) 的最大元素索引
print('\nIndices of max elements along axis 0 (columns):', np.argmax(a, axis=0))
# 沿轴 1 (行) 的最大元素索引
print('Indices of max elements along axis 1 (rows):', np.argmax(a, axis=1))
# 最小元素的索引 (展平后)
print('\nIndex of min element (flattened):', np.argmin(a))
# 最小元素的值
print('Value of min element:', a.flat[np.argmin(a)])
# 沿轴 0 (列) 的最小元素索引
print('\nIndices of min elements along axis 0 (columns):', np.argmin(a, axis=0))
# 沿轴 1 (行) 的最小元素索引
print('Indices of min elements along axis 1 (rows):', np.argmin(a, axis=1))

输出:

Original array:
[[30 40 70]
[80 20 10]
[50 90 60]]
Index of max element (flattened): 7
Value of max element: 90
Indices of max elements along axis 0 (columns): [1 2 0]
Indices of max elements along axis 1 (rows): [2 0 1]
Index of min element (flattened): 5
Value of min element: 10
Indices of min elements along axis 0 (columns): [0 1 1]
Indices of min elements along axis 1 (rows): [0 2 0]

返回 非零 (non-zero) 元素的索引。结果是一个元组 (tuple),其中包含按维度划分的数组,每个数组包含该维度中非零元素的索引。

import numpy as np
a = np.array([
[30, 40, 0],
[0, 20, 10],
[50, 0, 60]
])
print('Original array:')
print(a)
print('\nIndices of non-zero elements:')
nonzero_indices = np.nonzero(a)
print(nonzero_indices)
# 使用这些索引访问非零元素
print('\nNon-zero elements:')
print(a[nonzero_indices])

输出:

Original array:
[[30 40 0]
[ 0 20 10]
[50 0 60]]
Indices of non-zero elements:
(array([0, 0, 1, 1, 2, 2]), array([0, 1, 1, 2, 0, 2]))
Non-zero elements:
[30 40 20 10 50 60]

返回给定条件为真的位置的索引。输出格式与 nonzero 类似。也可以像 三元运算符 (ternary operator) 一样使用:np.where(condition, x, y) 在条件为真时返回 x 中的元素,在条件为假时返回 y 中的元素。

import numpy as np
x = np.arange(9.).reshape(3, 3)
print('Original array:')
print(x)
condition = x > 3
print('\nCondition (x > 3):')
print(condition)
print('\nIndices where condition is true:')
indices = np.where(condition)
print(indices)
print('\nElements where condition is true:')
print(x[indices])
# 像三元运算符一样使用 where
result = np.where(condition, x, -1) # 将小于等于 3 的元素替换为 -1
print('\nArray with elements <= 3 replaced by -1:')
print(result)

输出:

Original array:
[[0. 1. 2.]
[3. 4. 5.]
[6. 7. 8.]]
Condition (x > 3):
[[False False False]
[False True True]
[ True True True]]
Indices where condition is true:
(array([1, 1, 2, 2, 2]), array([1, 2, 0, 1, 2]))
Elements where condition is true:
[4. 5. 6. 7. 8.]
Array with elements <= 3 replaced by -1:
[[-1. -1. -1.]
[-1. 4. 5.]
[ 6. 7. 8.]]

返回满足给定条件的数组元素。它在应用条件之前会将数组 展平 (flatten)。

import numpy as np
x = np.arange(9.).reshape(3, 3)
print('Original array:')
print(x)
# 定义一个条件 (例如,元素是偶数整数)
condition = np.mod(x, 2) == 0
print('\nCondition (x % 2 == 0):')
print(condition)
# 使用条件提取元素
print('\nExtract elements using condition:')
print(np.extract(condition, x))

输出:

Original array:
[[0. 1. 2.]
[3. 4. 5.]
[6. 7. 8.]]
Condition (x % 2 == 0):
[[ True False True]
[False True False]
[ True False True]]
Extract elements using condition:
[0. 2. 4. 6. 8.]