我有一个像下面这样的数组:
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
