gpt4 book ai didi

python - 基于最小/最大值的 Numpy 动态数组切片

转载 作者:太空宇宙 更新时间:2023-11-03 20:13:30 25 4
gpt4 key购买 nike

我有一个 3 维 hape 数组(365, x, y),其中 36 对应于=每日数据。在某些情况下,沿时间轴 axis=0 的所有元素都是 np.nan

沿 axis=0 的每个点的时间序列如下所示:

Image

我需要找到最大值(峰值数据)出现的索引,然后找到峰值两侧的两个最小值。

import numpy as np

a = np.random.random(365, 3, 3) * 10
a[:, 0, 0] = np.nan

peak_mask = np.ma.masked_array(a, np.isnan(a))
peak_indexes = np.nanargmax(peak_mask, axis=0)

我可以使用这样的方法找到峰值之前的最小值:

early_minimum_indexes = np.full_like(peak_indexes, fill_value=0)

for i in range(peak_indexes.shape[0]):
for j in range(peak_indexes.shape[1]):
if peak_indexes[i, j] == 0:
early_minimum_indexes[i, j] = 0
else:
early_mask = np.ma.masked_array(a, np.isnan(a))
early_loc = np.nanargmin(early_mask[:peak_indexes[i, j], i, j], axis=0)
early_minimum_indexes[i, j] = early_loc

绘制的峰和谷如下所示:

Image

对于大型数组(1m+元素)来说,这种方法在时间上是非常不合理的。有没有更好的方法使用 numpy 来做到这一点?

最佳答案

虽然在这种情况下使用屏蔽数组可能不是有效的解决方案,但它允许您在特定轴上执行屏蔽操作,同时或多或少保留形状,这非常方便。请记住,在许多情况下,屏蔽函数最终仍会复制屏蔽数据。

您当前的代码中的想法基本上是正确的,但是您错过了一些技巧,例如能够否定和组合掩码。此外,预先将掩码分配为 bool 值会更有效,而且还有像 np.full(..., 0) -> np.zeros(..., dtype=bool) 这样的小问题。

让我们倒过来解决这个问题。假设您有一个性能良好且具有峰值的一维数组,例如 a1。您可以使用掩蔽轻松找到最大值和最小值(或索引),如下所示:

peak_index = np.nanargmax(a1)
mask = np.zeros(a1.size, dtype=np.bool)
mask[peak:] = True
trough_plus = np.nanargmin(np.ma.array(a1, mask=~mask))
trough_minus = np.nanargmin(np.ma.array(a1, mask=mask))

这尊重这样一个事实:掩码数组相对于正常的 numpy bool 索引翻转掩码的含义。最大值出现在 trough_plus 的计算中也是可以的,因为它保证不会是最小值(除非您遇到 all-nan 情况)。

现在,如果 a1 已经是一个掩码数组(但仍然是一维),您可以做同样的事情,但暂时组合掩码。例如:

a1 = np.ma.array(a1, mask=np.isnan(a1))
peak_index = a1.argmax()
mask = np.zeros(a1.size, dtype=np.bool)
mask[peak:] = True
trough_plus = np.ma.masked_array(a1, mask=a.mask | ~mask).argmin()
trough_minus (np.ma.masked_array(a1, mask=a.mask | mask).argmin()

同样,由于掩码数组具有反向掩码,因此使用 | 而不是 & 组合掩码非常重要,就像普通的 numpy bool 掩码一样。在这种情况下,无需调用 argmax 和 argmin 的 nan 版本,因为所有 nan 都已被屏蔽。

鉴于 numpy 函数中 axis 关键字的流行,希望从这里可以清楚地了解多维度的泛化:

a = np.ma.array(a, mask=np.isnan(a))
peak_indices = a.argmax(axis=0).reshape(1, *a.shape[1:])
mask = np.arange(a.shape[0]).reshape(-1, *(1,) * (a.ndim - 1)) >= peak_indices

trough_plus = np.ma.masked_array(a, mask=~mask | a.mask).argmin(axis=0)
trough_minus = np.ma.masked_array(a, mask=mask | a.mask).argmin(axis=0)

N维掩蔽技术来自Fill mask efficiently based on start indices ,正是出于这个目的才被要求的。

关于python - 基于最小/最大值的 Numpy 动态数组切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58594237/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com