Luk
Luk

Reputation: 1149

Python: Comparison between a 1D and a 2D array, asking where both arrays have nonzero entries

Consider two arrays, array1 and array2, where array1 is 1D and array2 is 2D:

array1 =  [  0    0  -80 -60    0 -30 ... ] 

array2 = [[-50    0  -20   0  -70 -80 ...], 
          [  0    0    0 -70  -40   0 ...],
          [  0  -50  -30 -60    0   0 ...],
           ...                        ]

Here is what I want to achieve: I want to compare array1 with each row of array2. Whenever both array1 and the respective row of array2 have entries that are nonzero, I want to increment a counter. In the end, I want to have an array, whose entries correspond to the counters value for every comparison.

Take the array from above as an example: The output would be:

[ 2, 1, 2 ] 

I hope that is clear.

Now, here is the tricky part: I do not want to use any for-loops. I want to achieve this using numpy-methods only!

I started working on this, but I am a bit lost. Nevertheless, here are some of my ideas:

indices1 = array1.nonzero() 
indices2 = array2.nonzero()
equal_entries = np.where(np.equal(indices1, indices2))

Assuming that both array1 and array2 are 1D, this will return a numpy-array, whose entries give the indices where both arrays have nonzero elements. That's what I want. Almost. Only, I want the length of this array. And - as array2 is 2D - I want this length for every comparison between array1 and each row of array2. It might be, that equal_entries = np.where(np.equal(indices1, indices2)) works fine, even if array2 is 2D. So, this line might return a 2D numpy-array, where each row gives the elements where array1 and the respective row of array2 both have nonzero elements. Not sure though. But even, if it does, I am left with finding the number of elements in each row of the result without using a for-loop.

Any ideas?

Upvotes: 0

Views: 70

Answers (1)

Niklas Mertsch
Niklas Mertsch

Reputation: 1489

You can use array != 0 to get an array like [False, False, True, True, False, True, ...] for array1.

You do that for both arrays and use & to only get True where both arrays are zero.

Then you take the row-wise sum.

np.sum((array1 != 0) & (array2 != 0), axis=1)

If it is not intuitive that array1 and array2 compare themselves using rows and not columns of array2 (e.g. if array2 is quadratic), you can explicitly shape array1 as a row-vector:

np.sum((array1[np.newaxis, :] != 0) & (array2 != 0), axis=1)

General notes:

  • If you want numpy to count something, generate a boolean array and count the True entries using np.sum().
  • If you want to perform a reducing operation (like sum) row- or column-wise, use the axis parameter: You give it the axis you want to reduce, so if you want the sum per row (axis 0), you want to reduce along all columns (axis 1), you use np.sum(..., axis=1).

Upvotes: 1

Related Questions