Home > Back-end >  Simple numpy broadcasting
Simple numpy broadcasting

Time:08-08

I'm sure this question has an answer already somewhere, but I'm having trouble finding it since there are so many broadcasting questions, so perhaps someone can either point to it or answer directly.

I want to apply a function to each element of a NumPy array.

I have:

def test1(x):
    return np.sum(x)
def test2(y):
    return test1([5.0, y])
test2([1.0,2.0,3.0])
# I want the result to be [6.0, 7.0, 8.0]
# But I get TypeError: unsupported operand type(s) for  : 'float' and 'list'

How can I do this?

In Julia it would be:

test2.([1.0,2.0,3.0])

Thanks

CodePudding user response:

Here's the full error message - which for some reason you decided wasn't relevant!

In [99]: def test1(x):
    ...:     return np.sum(x)
    ...: def test2(y):
    ...:     return test1([5.0, y])
    ...: test2([1.0,2.0,3.0])
/usr/local/lib/python3.8/dist-packages/numpy/core/fromnumeric.py:86: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
Traceback (most recent call last):
  Input In [99] in <cell line: 5>
    test2([1.0,2.0,3.0])
  Input In [99] in test2
    return test1([5.0, y])
  Input In [99] in test1
    return np.sum(x)
  File <__array_function__ internals>:180 in sum
  File /usr/local/lib/python3.8/dist-packages/numpy/core/fromnumeric.py:2298 in sum
    return _wrapreduction(a, np.add, 'sum', axis, dtype, out, keepdims=keepdims,
  File /usr/local/lib/python3.8/dist-packages/numpy/core/fromnumeric.py:86 in _wrapreduction
    return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
TypeError: unsupported operand type(s) for  : 'float' and 'list'

Let's add a debugging print to test1:

In [100]: def test1(x):
     ...:     print(x)
     ...:     return np.sum(x)
     ...: test2([1.0,2.0,3.0])
[5.0, [1.0, 2.0, 3.0]]
....

Do you understand why x is this list - with a number and a list?

np.sum is a numpy function, and like most, it converts the input into an array first:

In [101]: np.array([5.0, [1.0, 2.0, 3.0]])
<ipython-input-101-79819e7b65b8>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  np.array([5.0, [1.0, 2.0, 3.0]])
Out[101]: array([5.0, list([1.0, 2.0, 3.0])], dtype=object)

If we pass an array instead, we still get the ragged array warning, but it runs:

In [102]: test2(np.array([1,2,3]))
[5.0, array([1, 2, 3])]
/usr/local/lib/python3.8/dist-packages/numpy/core/fromnumeric.py:86: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
  return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
Out[102]: array([6., 7., 8.])

np.sum can operate on the 5.0 and np.array([1,2,3])

If we use the python sum instead, the number and array do add - without that intermediate step of creating a ragged array:

In [104]: sum([5, np.array([1,2,3])])
Out[104]: array([6, 7, 8])

Or the full function sequence:

In [105]: def test1(x):
     ...:     return sum(x)
     ...: def test2(y):
     ...:     return test1([5.0, y])
     ...: test2(np.array([1.0,2.0,3.0]))
Out[105]: array([6., 7., 8.])
  • Related