user109387
user109387

Reputation: 704

Eliminating array rows that do not meet a matching criterion

Consider an array, M, made up of pairs of elements. (I've used spaces to emphasize that we will be dealing with element PAIRS). The actual arrays will have a large number of rows, and 4,6,8 or 10 columns.

import numpy as np

M = np.array([[1,3,  2,1,  4,2,  3,3],
              [3,5,  6,9,  5,1,  3,4],
              [1,3,  2,4,  3,4,  7,2],
              [4,5,  1,2,  2,1,  2,3],
              [6,4,  4,1,  6,1,  4,7],
              [6,7,  7,6,  9,7,  6,2],
              [5,3,  1,5,  3,3,  3,3]])

PROBLEM: I want to eliminate rows from M having an element pair that has no common elements with any of the other pairs in that row.

In array M, the 2nd row and the 4th row should be eliminated. Here's why:
2nd row: the pair (6,9) has no common element with (3,5), (5,1), or (3,4)
4th row: the pair (4,5) has no common element with (1,2), (2,1), or (2,3)

I'm sure there's a nice broadcasting solution, but I can't see it.

Upvotes: 2

Views: 61

Answers (2)

Akshay Sehgal
Akshay Sehgal

Reputation: 19322

Another way of solving this would be the following -

M = np.array([[1,3,  2,1,  4,2,  3,3],
              [3,5,  6,9,  5,1,  3,4],
              [1,3,  2,4,  3,4,  7,2],
              [4,5,  1,2,  2,1,  2,3],
              [6,4,  4,1,  6,1,  4,7],
              [6,7,  7,6,  9,7,  6,2],
              [5,3,  1,5,  3,3,  3,3]])

MM = M.reshape(M.shape[0],-1,2)

matches_M = np.any(MM[:,:,None,:,None] == MM[:,None,:,None,:], axis=(-1,-2))
mask = ~np.eye(MM.shape[1], dtype=bool)[None,:]

is_valid = np.all(np.any(matches_M&mask, axis=-1), axis=-1)
M[is_valid]
array([[1, 3, 2, 1, 4, 2, 3, 3],
       [1, 3, 2, 4, 3, 4, 7, 2],
       [6, 4, 4, 1, 6, 1, 4, 7],
       [6, 7, 7, 6, 9, 7, 6, 2],
       [5, 3, 1, 5, 3, 3, 3, 3]])

Upvotes: 1

Quang Hoang
Quang Hoang

Reputation: 150745

This is a broadcasting solution. Hope it's self-explained:

a = M.reshape(M.shape[0],-1,2)

mask = ~np.eye(a.shape[1], dtype=bool)[...,None]

is_valid = (((a[...,None,:]==a[:,None,...])&mask).any(axis=(-1,-2))
            |((a[...,None,:]==a[:,None,:,::-1])&mask).any(axis=(-1,-2))
           ).all(-1)

M[is_valid]

Output:

array([[1, 3, 2, 1, 4, 2, 3, 3],
       [1, 3, 2, 4, 3, 4, 7, 2],
       [6, 4, 4, 1, 6, 1, 4, 7],
       [6, 7, 7, 6, 9, 7, 6, 2],
       [5, 3, 1, 5, 3, 3, 3, 3]])

Upvotes: 1

Related Questions