Reputation: 19684
I have this symmetric matrix:
>>> X = np.array([[2,0,1,0],[0,0,0,0],[1,0,1,0], [0,0,0,0]])
array([[2, 0, 1, 0],
[0, 0, 0, 0],
[1, 0, 1, 0],
[0, 0, 0, 0]])
What's the most concise way to remove rows and columns that are allzero? Such that I get:
array([[2, 1],
[1, 1]])
Is there a term for this operation, or a one-liner to do it?
I tried the following, but it did not work:
mask = np.all(X == 0, axis=1)
X[not(mask),not(mask)]
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Upvotes: 0
Views: 624
Reputation: 118
Have you had a look what np.all
returns? It's an array, so you can't simply 'not' it. Rather than that, you could try np.any
('not all = any' - good old de Morgan):
mask = np.any(X, axis=1)
Then you can get your 'filtered' X like this:
X[mask][:, mask]
Note that once you do that, you may potentially end up with new zeroes-filled rows and columns, so you might want to repeat this operation several times.
Upvotes: 1
Reputation: 758
rows = np.argwhere(np.sum(X, axis=0) == 0).flatten()
cols = np.argwhere(np.sum(X, axis=1) == 0).flatten()
np.delete(np.delete(X, rows, axis=0), cols, axis=1)
Upvotes: 1
Reputation: 19684
This appears to work but seems dumb:
>>> mask = np.all(X == 0, axis=1)
>>> X = X[~mask, :]
>>> X = X[:, ~mask]
>>> X
array([[2, 1],
[1, 1]])
Upvotes: 0