Skip to main content
 首页 » 编程设计

python之如何使用 numpy 在可变长度数组的数组中查找最小值/最大值

2025年05月04日15softidea

我有一个像下面这样的数组:

data = [ 
  [-20], 
  [-23], 
  [-41], 
  [1, 2, 3], 
  [2, 3], 
  [5, 6, 7, 8, 9], 
] 
arr = np.array(data) 

如何使用 numpy 查找 data 中每个数组的最小值/最大值? np.min 和 np.max 似乎都不起作用,即使我指定了不同的轴。 所需的结果如下所示:

>>> np.findmin(arr) 
array([-20, -23, -41, 1, 2, 5]) 
>>> np.findmax(arr) 
array([-20, -23, -41, 3, 3, 9]) 

此外,我不完全清楚为什么 np.min 和 np.max 不起作用。如果给定的数组具有定义明确的轴,其中每一行都有固定数量的列,它们也许只会按照我想要的方式工作?如果有人可以解释这一点,我很想知道。

请您参考如下方法:

这是可能的,但这不是 numpy 擅长的事情。一种可能的解决方案是用 nan 填充数组并像这样使用 np.nanmax

import numpy as np 
 
def pad_array(arr): 
    M = max(len(a) for a in arr) 
    return np.array([a + [np.nan] * (M - len(a)) for a in arr]) 
 
data = [ 
  [-20], 
  [-23], 
  [-41], 
  [1, 2, 3], 
  [2, 3], 
  [5, 6, 7, 8, 9], 
] 
arr = pad_array(data) 
# array([[-20.,  nan,  nan,  nan,  nan], 
#        [-23.,  nan,  nan,  nan,  nan], 
#        [-41.,  nan,  nan,  nan,  nan], 
#        [  1.,   2.,   3.,  nan,  nan], 
#        [  2.,   3.,  nan,  nan,  nan], 
#        [  5.,   6.,   7.,   8.,   9.]]) 
 
np.nanmin(arr, axis=1) #array([-20., -23., -41.,   1.,   2.,   5.]) 
np.nanmax(arr, axis=1) #array([-20., -23., -41.,   3.,   3.,   9.]) 

不过,这并不比常规的列表推导式快。 np.min 和 np.max 正在 工作,但 numpy 不支持参差不齐的数组,所以 np.array(data ) 正在创建一个一维对象数组,而 np.min 正在为您提供最小的 object - 与您获得的相同使用 Python 的内置 min 函数——同样适用于 np.max。

下面是比较创建填充数组和使用普通列表理解的时间

%%timeit 
arr = np.array(pad_array(data)) 
np.nanmin(arr, axis=1) 
10000 loops, best of 3: 27 µs per loop 
 
%timeit [min(row) for row in data] 
1000000 loops, best of 3: 1.26 µs per loop 

这有点做作,因为我在 pad_array 中使用了列表推导式和生成器表达式,所以按理说,单个列表推导式会更快,但如果你遇到这样的情况在您只需要创建一次填充数组的地方,单个列表理解仍然会更快。

%timeit np.nanmin(arr, axis=1) 
100000 loops, best of 3: 13.3 µs per loop 

编辑:

您可以使用 np.vectorize 制作 Python 内置 max 和 min 函数的矢量化版本

vmax = np.vectorize(max) 
vmax(data) #array([-20, -23, -41,   3,   3,   9]) 

它仍然不比列表理解快...

%timeit vmax(data) 
10000 loops, best of 3: 25.6 µs per loop 

编辑 2

为了完整性/正确性,值得指出的是,numpy 解决方案比纯 Python 列表理解解决方案的扩展性更好。假设我们有 600 万行而不是 6 行,并且需要执行多个元素方面的操作,numpy 会更好。例如,如果我们有

data = [ 
  [-20], 
  [-23], 
  [-41], 
  [1, 2, 3], 
  [2, 3], 
  [5, 6, 7, 8, 9], 
] * 1000000 
 
arr = pad_array(data) #this takes ~6 seconds 

时间安排更有利于 numpy

%timeit [min(row) for row in data] 
1 loops, best of 3: 1.05 s per loop 
 
%timeit np.nanmin(arr, axis=1) 
10 loops, best of 3: 111 ms per loop