[Numpy-discussion] Difference between shape=() and shape=(1,)

John Reid j.reid@mail.cryst.bbk.ac...
Wed Jul 14 03:54:32 CDT 2010


Benjamin Root wrote:
> On Tue, Jul 13, 2010 at 12:45 PM, Kurt Smith <kwmsmith@gmail.com 
> <mailto:kwmsmith@gmail.com>> wrote:
> 
>     On Tue, Jul 13, 2010 at 11:54 AM, John Reid
>     <j.reid@mail.cryst.bbk.ac.uk <mailto:j.reid@mail.cryst.bbk.ac.uk>>
>     wrote:
>      > Hi,
>      >
>      > I have some arrays of various shapes in which I need to set any
>     NaNs to
>      > 0. I have been doing the following:
>      >
>      > a[numpy.where(numpy.isnan(a)] = 0.
>      >
>      >
>      >
>      > as you can see here:
>      >
>      > In [20]: a=numpy.ones(2)
>      >
>      > In [21]: a[1]=numpy.log(-1)
>      >
>      > In [22]: a
>      > Out[22]: array([  1.,  NaN])
>      >
>      > In [23]: a[numpy.where(numpy.isnan(a))]=0.
>      >
>      > In [24]: a
>      > Out[24]: array([ 1.,  0.])
>      >
>      >
>      >
>      > Unfortunately, I've just discovered that when a.shape == () this
>     doesn't
>      > work at all. For example:
>      >
>      > In [41]: a=numpy.array((1.))
>      >
>      > In [42]: a.shape
>      > Out[42]: ()
>      >
>      > In [43]: a[numpy.where(numpy.isnan(a))]=0.
>      >
>      > In [44]: a
>      > Out[44]: array(0.0)
>      >
>      >
>      >
>      >
>      >
>      > but if the shape is (1,), everything is ok:
>      >
>      > In [47]: a=numpy.ones(1)
>      >
>      > In [48]: a.shape
>      > Out[48]: (1,)
>      >
>      > In [49]: a[numpy.where(numpy.isnan(a))]=0.
>      >
>      > In [50]: a
>      > Out[50]: array([ 1.])
>      >
>      >
>      >
>      > What's the difference between the 2 arrays with different shapes?
>      >
>      > If I pass a scalar into numpy.asarray() why do I get an array of
>     shape
>      > () back? In my case this has caused a subtle bug.
>      >
>      > Is there a better way to set NaNs in an array to 0?
> 
>     You could make use of np.atleast_1d, and then everything would be
>     canonicalized:
> 
>     In [33]: a = np.array(np.nan)
> 
>     In [34]: a
>     Out[34]: array(nan)
> 
>     In [35]: a1d = np.atleast_1d(a)
> 
>     In [36]: a1d
>     Out[36]: array([ NaN])
> 
>     In [37]: a
>     Out[37]: array(nan)
> 
>     In [38]: a1d.base is a
>     Out[38]: True
> 
>     In [39]: a1d[np.isnan(a1d)] = 0.
> 
>     In [40]: a1d
>     Out[40]: array([ 0.])
> 
>     In [41]: a
>     Out[41]: array(0.0)
> 
>     So Keith's nan_replace would be:
> 
>     In [42]: def nan_replace(a, fill=0.0):
>       ....:     a_ = np.atleast_1d(a)
>       ....:     a_[np.isnan(a_)] = fill
>       ....:
> 
> 
> Maybe I am missing something subtle, but what about numpy's nan_to_num() 
> function?

That sounds useful but I should have said: sometimes I need to replace 
other values that aren't NaNs.

Anyway thanks for all the tips everyone. Here's what I ended up with:

def array_replace(a, loc, fill):
     """
     Replace the values in a at the locations, loc, with the value, fill.

     For example:
     In [32]: a=numpy.arange(10)+1

     In [33]: array_replace(a, a%3==1, 0)
     Out[33]: array([0, 2, 3, 0, 5, 6, 0, 8, 9, 0])

     or for 0-d arrays:
     In [15]: b=numpy.array(3)

     In [16]: array_replace(b, b==3, 2)
     Out[16]: array([2])

     In [17]: b
     Out[17]: array(2)
     """
     a_ = numpy.atleast_1d(a)
     a_[numpy.atleast_1d(loc)] = fill
     return a_




More information about the NumPy-Discussion mailing list