如何在NumPy数组每行中仅保留严格递增数值的首次出现(其余置0)
如何在NumPy数组每行中仅保留严格递增数值的首次出现(其余置0)
看起来你需要处理NumPy数组的每行,只保留那些严格大于该行之前所有保留值的最大值的元素的首次出现,其余元素置0——也就是每行里只保留“创纪录”的新高值,其他都清零对吧?刚好可以用NumPy的累积最大值函数来实现,完全不用显式循环,非常符合NumPythonic的风格。
解决方案代码
import numpy as np arr = np.array([ [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5], [1, 1, 2, 2, 2, 3, 2, 2, 3, 3, 3, 4, 4], [3, 2, 1, 2, 1, 1, 2, 3, 4, 5, 4, 3, 2]]) # 计算每行的累积最大值(到每个位置为止的历史最高值) cum_max = np.maximum.accumulate(arr, axis=1) # 创建布尔掩码,标记需要保留的位置 mask = np.zeros_like(arr, dtype=bool) mask[:, 0] = True # 每行第一个元素默认保留 # 从第二列开始,判断当前元素是否严格大于前一个位置的累积最大值 mask[:, 1:] = arr[:, 1:] > cum_max[:, :-1] # 生成结果:保留掩码标记的元素,其余置0 out = arr * mask print(out)
代码逻辑解释
- 计算累积最大值:
np.maximum.accumulate(arr, axis=1)会沿着每行的方向,逐个计算到当前位置为止的最大值,这样我们就能快速获取每行到每个位置之前的“历史最高值”。 - 构建保留掩码:
- 先创建一个和原数组形状一致的全False布尔数组,作为掩码基础。
- 每行的第一个元素没有前置元素,直接标记为True,保留原值。
- 从第二列开始,判断当前元素是否严格大于前一个位置的累积最大值(也就是到前一个位置的历史最高),如果是,说明这个元素是新的新高,标记为True。
- 生成最终结果:用原数组乘以掩码,True对应的位置保留原值,False对应的位置自动变为0。
运行结果
执行代码后,输出完全符合你给出的示例:
[[1 0 0 2 0 0 3 0 0 4 0 5 0] [1 0 2 0 0 3 0 0 0 0 0 4 0] [3 0 0 0 0 0 0 0 4 5 0 0 0]]
备注:内容来源于stack exchange,提问作者alpelito7
相关产品推荐
相关产品推荐

