在没有 Python 循环的情况下制作一个单调的 numpy 数组
Posted
技术标签:
【中文标题】在没有 Python 循环的情况下制作一个单调的 numpy 数组【英文标题】:Make a numpy array monotonic without a Python loop 【发布时间】:2015-04-18 06:42:14 【问题描述】:我有一个值的一维数组,它应该是单调的(假设是递减的),但是有些随机区域的值随着索引的增加而增加。
我需要一个数组,其中每个区域都替换为其前面的值,以便对结果数组进行排序。
所以如果给定的数组是:
a = np.array([10.0, 9.5, 8.0, 7.2, 7.8, 8.0, 7.0, 5.0, 3.0, 2.5, 3.0, 2.0])
我希望结果是
b = np.array([10.0, 9.5, 8.0, 7.2, 7.2, 7.2, 7.0, 5.0, 3.0, 2.5, 2.5, 2.0])
这是一个图形表示:
我知道如何使用 Python 循环来实现它,但是有没有办法使用 NumPy 机器来做到这一点?
为了清晰起见的 Python 代码:
b = np.array(a)
for i in range(1, b.size):
if b[i] > b[i-1]:
b[i] = b[i-1]
【问题讨论】:
为什么要关注“没有循环”?无论您是编写显式循环,还是循环是在某个模块/包的导入函数中完成的,它仍然存在。没有很多方法可以对不涉及循环的一系列值执行某些操作,除非您想将整个循环完全展开为线性操作序列,这由于几个不同的原因而很难看 - 可移植性、灵活性,代码大小等... @twalberg 我认为在使用 NumPy 时尽量避免 Python 循环是很常见的,因为如果在 C 中实现的函数内进行迭代,性能通常会提高。代码更短的情况也经常发生清洁工。 这是处理大型数据集时的有效点。然而,在这个例子中(并且没有任何迹象表明“真正的”问题要大几个数量级),我认为将 Python 列表转换为 C 循环可以处理的数据结构,然后将其转换回适当的 Python 数据结构,可能会避免任何潜在的收益,而不仅仅是使用 Python 循环来迭代十几个条目......最好在盲目地试图消除它之前验证循环是一个问题...... @twalberg 够公平的;我应该提到的是,实际数据确实有数千个元素,并且已经采用 NumPy 数组的形式。然而,这个问题也有教育目的。 【参考方案1】:您可以在数组中移动时使用np.minimum.accumulate
收集最小值:
>>> np.minimum.accumulate(a)
array([ 10. , 9.5, 8. , 7.2, 7.2, 7.2, 7. , 5. , 3. ,
2.5, 2.5, 2. ])
在数组中的每个元素处,此函数返回到目前为止看到的最小值。
如果你想让一个数组单调递增,你可以使用np.maximum.accumulate
。
NumPy 中的许多其他通用函数都有一个 accumulate
方法来模拟遍历数组,将函数应用于每个元素并将返回的值收集到相同大小的数组中。
【讨论】:
哇。我不知道.accumulate
!这非常接近 Python2 reduce
(或 Python3 functools.reduce
),对吗?
非常相似 - accumulate
存储对每个元素的操作结果,返回一个相同长度的数组,而 unfunc 的 reduce
方法只显示最终结果(折叠数组)。
哦,是的,你是对的。所以reduce
基本上会返回accumulate
返回的最后一个元素。以上是关于在没有 Python 循环的情况下制作一个单调的 numpy 数组的主要内容,如果未能解决你的问题,请参考以下文章
在没有任何库的情况下从多个图像用 Javascript 制作 GIF
是否可以在没有迭代器变量的情况下实现 Python for range 循环?