【问题标题】:Get beginning and end of range in array获取数组范围的开始和结束
【发布时间】:2018-10-03 11:24:42
【问题描述】:

假设我有一个信号,比如一个正弦波:

x = np.arange(100)
y = np.sin(x/10)

当我绘制此图时,我想用红色突出显示 y 的值高于某个阈值的区域,例如0.7。我想过做这样的事情

region = [i for i, e in enumerate(y) if e >= 0.7]
fig, ax = plt.subplots()
ax.plot(x, y)

k = region [0]
for i in region:
    if i-k == 1:
       ax.axvspan(k, i+1, facecolor='red', alpha=0.2)
    k = i

plt.show()

添加+1 是因为我想“包含”突出显示区域中的最后一个点。

但是,这会产生重叠的axvspans,这意味着第一个和最后一个会“更轻”(因为我使用的是alpha = 0.2),如图:

是否有另一种(可能更简单)的方法来实现这一点?

【问题讨论】:

    标签: python arrays numpy matplotlib


    【解决方案1】:

    一种方法是对y 应用掩码以查找值高于阈值的位置。然后,您需要找到掩码值为True 的第一个和最后一个匹配项。这可以通过使用this question 的答案找到True-FalseFalse-True 转换来完成:

    x = np.arange(100)
    y = np.sin(x/10)
    
    fig, ax = plt.subplots()
    ax.plot(x, y)
    
    mask = y >= 0.7
    
    first_vals = np.argwhere((~mask[:-1] & mask[1:]))  # Look for False-True transitions
    last_vals = np.argwhere((mask[:-1] & ~mask[1:])) + 1  # Look for True-False transitions
    
    for start, stop in zip(first_vals, last_vals):
        ax.axvspan(start, stop, facecolor='red', alpha=0.2)
    
    plt.show()
    

    引入第二个条件意味着您必须使用numpy.logical_or。如果掩码的第一个值为True,则可能需要引入一些额外的检查:

    mask = np.logical_or(y>0.7, y==0)
    
    if mask[0]:
        first_vals = np.argwhere((~mask[:-1] & mask[1:]))  # Look for False-True transitions
        last_vals = np.argwhere((mask[:-1] & ~mask[1:])) + 1 # Look for True-False transitions
        first_vals = np.insert(first_vals, 0, 0, axis=0)
    
    for start, stop in zip(first_vals, last_vals):
        ax.axvspan(start, stop, facecolor='red', alpha=0.2)
    

    【讨论】:

    • 如果你比较你的图形右侧边缘的 x 值和 OP 的图形,你会发现你在两个补丁的右侧都缺少一个切片(薄)。如果他/她将ax.axvspan(k, i+1, facecolor='red', alpha=0.2) 替换为ax.axvspan(k, i, facecolor='red', alpha=0.2),这正是OP 所得到的。也许你应该使用>=0.7
    • @DavidG 这似乎是正确的方法。我现在想添加另一个区域,但如果我写 mask = (y >= 0.7) or (y == 0) 我会得到 ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
    • @Enzo 我已经更新了答案,看看对你有帮助吗?
    • @DavidG 这正是我想要的。谢谢你。虽然在您的回答中只找到了一个为零的区域,但我认为这是由于 x 不完全是 n*pi,因此 y 不会完全为零,对吧?
    • @Enzo 没错,第二个“接近零”区域的最接近 y 值是 0.02,然后是 -0.07,所以它没有捕捉到它们。您可能必须指定一些边界才能使值接近零
    猜你喜欢
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    相关资源
    最近更新 更多