【问题标题】:How to check is numpy 2d array "surrounded" by zeros如何检查 numpy 二维数组是否被零“包围”
【发布时间】:2018-04-07 00:03:43
【问题描述】:

是否有任何巧妙的方法来检查被零包围的 numpy 数组。

例子:

[[0,0,0,0],
 [0,1,2,0],
 [0,0,0,0]]

我知道我可以逐个元素地迭代它以找出答案,但我想知道我们可以在这里使用什么好技巧。 numpy 数组是浮点数,n x m 任意大小。

欢迎提出任何想法。

【问题讨论】:

  • 您只想检查给定数组是否至少有一个“被零包围”的事件?或者您想知道哪些元素被零包围?
  • 很抱歉,我很难说出这个问题。我想知道的是所有矩阵边界(周长?)元素为零。我对矩阵内部的内容不感兴趣。

标签: python arrays numpy


【解决方案1】:

您可以使用numpy.any() 来测试numpy 数组中是否有任何非零元素。

现在,要测试二维数组是否被零包围,您可以获取第一列和最后一列以及第一行和最后一行,并测试其中任何一个是否包含非零数字。

def zero_surrounded(array):
    return not (array[0,:].any() or array[-1,:].any() or array[:,0].any() or array[:,-1].any())

【讨论】:

  • 虽然这可能不是最短的解决方案,但语句的逻辑含义非常清楚,执行应该与最快的解决方案相当。有时简单和具体比简洁和聪明更好。
【解决方案2】:

我们可以通过构造两个子矩阵来检查这一点:

  • A[[0,-1]]第一行和最后一行,包括第一列和最后一列;和
  • A[1:-1,[0,-1]] 第一列和最后一列,不包括第一行和最后一行。

这些矩阵的所有值都应该为零,所以我们可以使用:

if np.all(A[[0,-1]] == 0) and np.all(A[1:-1,[0,-1]] == 0):
    # ...
    pass

这适用于任意二维数组,但不适用于任意深度的数组。但是,我们也可以为此使用技巧。

对于任意矩阵,我们可以使用:

def surrounded_zero_dim(a):
    n = a.ndim
    sel = ([0,-1],)
    sli = (slice(1,-1),)
    return all(np.all(a[sli*i+sel] == 0) for i in range(n))

严格来说没有必要使用切片,但它可以防止对某些值进行两次检查。

【讨论】:

    【解决方案3】:

    不是最快的,但可能是最短的(因此是“整洁”)的方式:

    surrounded = np.sum(a[1:-1, 1:-1]**2) == np.sum(a**2)
    print(surrounded)  # True
    

    这里,a 是数组。

    这会将所有平方元素的总和与所有平方元素的总和进行比较,边界上的元素除外。如果我们忽略平方,正负边界值加起来为零的情况会产生错误的答案。

    【讨论】:

    • 绝对是一种创造性的解决方法,但我担心它会降低代码的可读性,就理解意图而言。
    • 为什么不用abs() 而不是**2
    • 这可能不起作用。如果这是一个复数矩阵,a**2 仍然可以包含相互抵消的负值。
    • @jmd_dk: 如果矩阵有复数呢?
    • 请注意,对于浮点数,即使 a 不为零,a**2 也可以为零,这要归功于下溢。对于 NumPy 的固定宽度整数类型,我们有可能在平方或求和中溢出。有太多的极端情况需要注意,这不是一个好的解决方案。
    猜你喜欢
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 1970-01-01
    • 2015-12-08
    • 1970-01-01
    相关资源
    最近更新 更多