6

Is there any neat way to check is numpy array surrounded by zeros.

Example:

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

I know I can iterate it element wise to find out but I wonder is there any nice trick we can use here. The numpy array is of floats, n x m of arbitrary size.

Any ideas are welcome.

2
  • You just want to check whether a given array has at least one "surrounded-by-zeroes" occurrence? Or you want to know which elements are surrounded by zeroes? Commented Oct 25, 2017 at 19:09
  • I'm sorry I find it hard to phrase this question. What I want is to know are all matrix boundary (perimeter?) elements zeros. I'm not interested what is inside a matrix. Commented Oct 25, 2017 at 19:13

3 Answers 3

4

You can use numpy.any() to test if there is any non-zero element in numpy array.

Now, to test if a 2D array is surrounded by zeroes, you can get first and last columns as well as first and last rows and test if any of those contains a non-zero number.

def zero_surrounded(array):
    return not (array[0,:].any() or array[-1,:].any() or array[:,0].any() or array[:,-1].any())
Sign up to request clarification or add additional context in comments.

1 Comment

While this may not be the shortest solution, the logical meaning of the statements is very clear, and the execution should be on par with the fastest possible solution. Sometimes simplicity and specificity is better than brevity and cleverness.
3

We can check this by constructing two submatrices:

  • A[[0,-1]] the first and the last row, including the first and last column; and
  • A[1:-1,[0,-1]] the first and last column, excluding the first and last row.

All the values of these matrices should be equal to zero, so we can use:

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

This works for an arbitrary 2d-array, but not for arrays with arbitrary depth. We can however use a trick for that as well.

For an arbitrary matrix, we can use:

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))

Using the slice is strictly speaking not necessary, but it prevents checking certain values twice.

Comments

2

Not the fastest, but perhaps the shortest (and hence a "neat") way of doing it:

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

Here, a is the array.

This compares the sum of all squared elements to the sum of all squared elements except for those on the boundary. If we left out the squaring, cases where positive and negative boundary values add up to zero would produce the wrong answer.

8 Comments

definitely a creative way of solving, but I worry it reduces the readability of the code as far as understanding the intent.
Why not using abs() instead of **2 ?
This probably does not work. If this is a matrix of complex numbers, a**2 can still contain negative values that cancel each other out.
@jmd_dk: what if the matrix has complex numbers?
Note that for floats, a**2 can be zero even if a is nonzero, thanks to underflow. And for NumPy's fixed-width integer types, we have a possibility of overflow either in the squaring or in the sum. There are too many corner cases to be aware of for this to be a good solution.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.