【问题标题】:Make a numpy array monotonic without a Python loop在没有 Python 循环的情况下制作一个单调的 numpy 数组
【发布时间】: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 数组的形式。然而,这个问题也有教育目的。

标签: python arrays numpy vectorization


【解决方案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 返回的最后一个元素。
猜你喜欢
  • 2017-03-25
  • 2021-01-29
  • 2023-03-25
  • 1970-01-01
  • 2019-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多