在没有 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 数组的主要内容,如果未能解决你的问题,请参考以下文章

Python 3:在没有任何循环的情况下重新运行当前函数

python数据框在没有循环的情况下每组应用函数

在没有任何库的情况下从多个图像用 Javascript 制作 GIF

是否可以在没有迭代器变量的情况下实现 Python for range 循环?

在没有库的情况下制作矩阵/在列表中没有任何内容的情况下插入嵌套列表

如何在没有 WHILE 循环锁定程序的情况下让 UDP 服务器在 Python 3 中监听?