42

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
Community
  • 1
  • 1
Milla Well
  • 3,193
  • 3
  • 35
  • 50

4 Answers4

103

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]])
ecatmur
  • 152,476
  • 27
  • 293
  • 366
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)
HYRY
  • 94,853
  • 25
  • 187
  • 187
  • You think, 1e-6 should be precise enough for most purposes? Should I learn this paramater? – Milla Well Jun 25 '12 at 12:09
  • @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. – heltonbiker Nov 23 '12 at 13:14
  • numpy now has `np.allclose` function which can make the code more readable https://docs.scipy.org/doc/numpy/reference/generated/numpy.allclose.html – oak Aug 29 '18 at 10:43
4

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.

yspreen
  • 1,759
  • 2
  • 20
  • 44
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,:]
travelingbones
  • 7,919
  • 6
  • 36
  • 43