[SciPy-Dev] Bug in use of np.sign() function with sparse csc_matrix?

Nathaniel Smith njs@pobox....
Sun Jan 22 16:04:26 CST 2012


On Sun, Jan 22, 2012 at 11:11 AM, Warren Weckesser
<warren.weckesser@enthought.com> wrote:
> On Sun, Jan 22, 2012 at 12:51 PM, Nathaniel Smith <njs@pobox.com> wrote:
>>
>> Numpy doesn't know anything about scipy sparse matrices in general -
>> they're just another random user defined python object. Generally you have
>> to call todense() before calling any numpy function on them.
>>
>> It wouldn't be that hard for you to implement sign() for csc or csr
>> matrices directly, since the pattern of nnz's doesn't change - just make a
>> new matrix that has the same indices and indptr arrays, but call sign() on
>> the data array.
>
>
> It was while experimenting with an implementation of exactly this idea,
> inspired by the pull request https://github.com/scipy/scipy/pull/138, that I
> stumbled across this behavior of sign().
>
> Attempting to use, say, np.cos results in an AttributeError.  np.abs works,
> because it is implemented in the _data_matrix class (a parent of
> csc_matrix):
>
> In [45]: m = csc_matrix([[1.0, -1.25], [1.75, 0.0]])
>
> In [46]: np.cos(m)
> ---------------------------------------------------------------------------
> AttributeError                            Traceback (most recent call last)
> /Users/warren/<ipython-input-46-a6e5f2a15c89> in <module>()
> ----> 1 np.cos(m)
>
> AttributeError: cos
>
> In [47]: np.abs(m)
> Out[47]:
> <2x2 sparse matrix of type '<type 'numpy.float64'>'
>     with 3 stored elements in Compressed Sparse Column format>
>
> In [48]: np.abs(m).todense()
> Out[48]:
> matrix([[ 1.  ,  1.25],
>         [ 1.75,  0.  ]])
>
> In [49]: np.sign(m)
> Out[49]: 1
>
> I haven't tracked down why sign(m) returns 1.

Huh, that is really weird. And I didn't even know about the thing
where a ufunc that's passed an object will dispatch to a method with
the same name... is that documented anywhere? Or is it just a quirk of
the built-in loops for the "O" dtype?

In [16]: np.sign({})
Out[16]: 1

In [17]: np.sign(object())
Out[17]: 1

In [18]: np.sign(np.sign)
Out[18]: 1

class Foo:
  def sign(self):
    return "asdf"

In [41]: np.sign(F())
Out[41]: -1

-- Nathaniel


More information about the SciPy-Dev mailing list