我有一个类似下面的数组:
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
无法正常工作。也许它们只会按照我想要的方式工作,如果给定的数组有明确定义的轴,其中每行有固定数量的列?如果有人能解释这一点,我很想知道。
答案 0 :(得分:4)
这是可能的,但这并不是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
答案 1 :(得分:2)
为什么不使用列表理解?
>>> d
[[-20], [-23], [-41], [1, 2, 3], [2, 3], [5, 6, 7, 8, 9]]
>>> [max(sublist) for sublist in d]
[-20, -23, -41, 3, 3, 9]
>>> [min(sublist) for sublist in d]
[-20, -23, -41, 1, 2, 5]
也适用于numpy数组:
>>> from numpy import array
>>> d
array([[-20], [-23], [-41], [1, 2, 3], [2, 3], [5, 6, 7, 8, 9]], dtype=object)
>>> [max(sublist) for sublist in d]
[-20, -23, -41, 3, 3, 9]
当然,你可以把结果作为数组。
>>> array([max(sublist) for sublist in d])
array([-20, -23, -41, 3, 3, 9])