46

I run a qr factorization in numpy which returns a list of ndarrays, namely Qand R:

>>> [q,r] = np.linalg.qr(np.array([1,0,0,0,1,1,1,1,1]).reshape(3,3))

R is a two-dimensional array, having pivoted zero-lines at the bottom (even proved for all examples in my test set):

>>> print r
[[ 1.41421356  0.70710678  0.70710678]
 [ 0.          1.22474487  1.22474487]
 [ 0.          0.          0.        ]]

. Now, I want to divide R in two matrices R_~:

[[ 1.41421356  0.70710678  0.70710678]
 [ 0.          1.22474487  1.22474487]]

and R_0:

[[ 0.          0.          0.        ]]

(extracting all zero-lines). It seems to be close to this solution: deleting rows in numpy array.

EDIT:
Even more interesting: np.linalg.qr() returns a n x n-matrix. Not, what I would have expected:

A := n x m
Q := n x m
R := n x m

4 Answers 4

107

Use np.all with an axis argument:

>>> r[np.all(r == 0, axis=1)]
array([[ 0.,  0.,  0.]])
>>> r[~np.all(r == 0, axis=1)]
array([[-1.41421356, -0.70710678, -0.70710678],
       [ 0.        , -1.22474487, -1.22474487]])
Sign up to request clarification or add additional context in comments.

4 Comments

@denfromufa axis=0 would remove all-zero columns.
that is obvious, what is problematic is that this filtering cannot be applied as is for axis=0, instead transpose is necessary
@denfromufa oh yeah, you need to do the subscript on the 1 axis: r[:, np.all(r == 0, axis=0)]
@denfromufa or s.compress(np.all(s == 0, axis=0), axis=1)
5

Because the data are not equal zero exactly, we need set a threshold value for zero such as 1e-6, use numpy.all with axis=1 to check the rows are zeros or not. Use numpy.where and numpy.diff to get the split positions, and call numpy.split to split the array into a list of arrays.

import numpy as np
[q,r] = np.linalg.qr(np.array([1,0,0,0,1,1,1,1,1]).reshape(3,3))
mask = np.all(np.abs(r) < 1e-6, axis=1)
pos = np.where(np.diff(mask))[0] + 1
result = np.split(r, pos)

3 Comments

You think, 1e-6 should be precise enough for most purposes? Should I learn this paramater?
@MillaWell the precision always depend on application. For example, a precision of one milimeter is very good for civil engineering, but very poor for mechanical engineering, and somewhat absurd for astronomy, for example.
numpy now has np.allclose function which can make the code more readable docs.scipy.org/doc/numpy/reference/generated/…
5

Since this is among the first google results to trim a 2D array of zero lines, I want to add my implementation to only remove leading and trailing zeros, in two dimensions:

p = np.where(t != 0)
t = t[min(p[0]) : max(p[0]) + 1, min(p[1]) : max(p[1]) + 1]

This assumes your array is called t and numpy is imported as np.

Comments

2

If you want to eliminate rows that have negligible entries, i'd use np.allclose.

zero_row_indices = [i for i in r.shape[0] if np.allclose(r[i,:],0)]
nonzero_row_indices =[i for i in r.shape[0] if not np.allclose(r[i,:],0)]
r_new = r[nonzero_row_indices,:]

Comments

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.