How to crop zero edges of a numpy array?
<p>I have this ugly, un-pythonic beast:</p>



<pre><code>def crop(dat, clp=True):
    '''Crops zero-edges of an array and (optionally) clips it to [0,1].

    Example:
    &gt;&gt;&gt; crop( np.array(
    ...       [[0,0,0,0,0,0],
    ...        [0,0,0,0,0,0],
    ...        [0,1,0,2,9,0],
    ...        [0,0,0,0,0,0],
    ...        [0,7,4,1,0,0],
    ...        [0,0,0,0,0,0]]
    ...     ))
    array([[1, 0, 1, 1],
           [0, 0, 0, 0],
           [1, 1, 1, 0]])
    '''
    if clp: np.clip( dat, 0, 1, out=dat )
    while np.all( dat[0,:]==0 ):
        dat = dat[1:,:]
    while np.all( dat[:,0]==0 ):
        dat = dat[:,1:]
    while np.all( dat[-1,:]==0 ):
        dat = dat[:-1,:]
    while np.all( dat[:,-1]==0 ):
        dat = dat[:,:-1]
    return dat
    # Below gets rid of zero-lines/columns in the middle
    #+so not usable.
    #dat = dat[~np.all(dat==0, axis=1)]      
    #dat = dat[:, ~np.all(dat == 0, axis=0)]
</code></pre>

<p>How do I tame it, and make it beautiful?</p>

<p>Definitely not the prettiest approach but wanted to try something else.</p>

<pre><code>def _fill_gap(a):
    """
    a = 1D array of `True`s and `False`s.
    Fill the gap between first and last `True` with `True`s.

    Doesn't do a copy of `a` but in this case it isn't really needed.
    """
    a[slice(*a.nonzero()[0].take([0,-1]))] = True
    return a

def crop3(d, clip=True):
    dat = np.array(d)
    if clip: np.clip(dat, 0, 1, out=dat)
    dat = np.compress(_fill_gap(dat.any(axis=0)), dat, axis=1)
    dat = np.compress(_fill_gap(dat.any(axis=1)), dat, axis=0)
    return dat
</code></pre>

<p>But it works.</p>

<pre><code>In [639]: crop3(np.array(
     ...:   [[0,0,0,0,0,0],
     ...:    [0,0,0,0,0,0],
     ...:    [0,1,0,2,9,0],
     ...:    [0,0,0,0,0,0],
     ...:    [0,7,4,1,0,0],
     ...:    [0,0,0,0,0,0]]))
Out[639]:
array([[1, 0, 1, 1],
       [0, 0, 0, 0],
       [1, 1, 1, 0]])
</code></pre>

python numpy crop