Is there a better way to assign a new value to a numpy array scalar?

亡梦爱人 提交于 2019-12-13 09:33:48

问题


I am doing some quick calculations on a scalar value from a numpy array. As it says in the documentation,

The primary advantage of using array scalars is that they preserve the array type (Python may not have a matching scalar type available, e.g. int16)...

But is there a better (faster, and more concise) way of assigning a new value to an existing array scalar than this:

>>> x = np.array(2.0, dtype='float32')

which works but is not that convenient (I am doing other arithmetic and want to preserve the type throughout).

This doesn't work for obvious reasons:

>>> x = np.array(1.0, dtype='float32')
>>> print(x, type(x))
1.0 <class 'numpy.ndarray'>
>>> x = 2.0
>>> print(x, type(x))
2.0 <class 'float'>

Neither does this:

>>> x = np.array(1.0, dtype='float32')
>>> x[] = 2.0
  File "<ipython-input-319-7f36071ff81d>", line 2
    x[] = 2.0
      ^
SyntaxError: invalid syntax

Nor this:

>>> x = np.array(1.0, dtype='float32')
>>> x[:] = 2.0
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-24-62cd4ca238ce> in <module>()
      1 x = np.array(1.0, dtype='float32')
----> 2 x[:] = 2.0

IndexError: too many indices for array

UPDATE:

Based on comments below (thanks) I have now realised that I am not actually using array scalars. x is a zero-dimensional array.

Here is how to create an array scalar:

>>> a = np.array((1.0, 2.0, 3.0), dtype='float32')
>>> x = a[0]
>>> print(x, type(x))
1.0 <class 'numpy.float32'>

Or simply:

>>> x = np.float32(1.0)
>>> print(x, type(x))
1.0 <class 'numpy.float32'>

回答1:


A 0d array can be modified, but an array scalar cannot:

In [199]: x = np.array(1.0, 'float32')
In [200]: x
Out[200]: array(1., dtype=float32)
In [201]: x.shape
Out[201]: ()
In [202]: x[...] = 2
In [203]: x
Out[203]: array(2., dtype=float32)
In [204]: x[()] =3
In [205]: x
Out[205]: array(3., dtype=float32)

You have to mutate x, not assign a new object to the variable.

That said, I don't see why one would want, or need, to do this.


This 0d array is not quite the same as an array scalar:

In [207]: y = np.float32(1)
In [208]: y[...] = 2
....
TypeError: 'numpy.float32' object does not support item assignment

Extracting an element from an array with indexing produces an array scalar:

In [210]: type(x[()])
Out[210]: numpy.float32

The float32 object has many of the array attributes, even methods, but it isn't quite same:

In [211]: x.shape
Out[211]: ()
In [212]: y.shape
Out[212]: ()

An array can be indexed with a tuple the same size as its shape. arr[1,2] is the same as arr[(1,2)]. The shape of x is (), so it can only be indexed with an empty tuple, x[()]. Similarly arr[:,:] works for a 2d array, but not for 1d. ... means, any number of slices, so works with x[...].

Enough of the __getitem__ has been defined for np.generic class objects to allow indexing like [...] and [()]. But the assignment has not been defined.

It might be useful to look at the class hierarchy of classes like np.ndarray, np.int_, np.float32, np.float, and np.int.

fuller quote

From your link: https://docs.scipy.org/doc/numpy-1.13.0/user/basics.types.html#array-scalars

NumPy generally returns elements of arrays as array scalars (a scalar with an associated dtype). Array scalars differ from Python scalars, but for the most part they can be used interchangeably (the primary exception is for versions of Python older than v2.x, where integer array scalars cannot act as indices for lists and tuples). There are some exceptions, such as when code requires very specific attributes of a scalar or when it checks specifically whether a value is a Python scalar. Generally, problems are easily fixed by explicitly converting array scalars to Python scalars, using the corresponding Python type function (e.g., int, float, complex, str, unicode).

The primary advantage of using array scalars is that they preserve the array type (Python may not have a matching scalar type available, e.g. int16). Therefore, the use of array scalars ensures identical behaviour between arrays and scalars, irrespective of whether the value is inside an array or not. NumPy scalars also have many of the same methods arrays do.

The 2nd paragraph is written the context of the 1st. It attempts to explain why elements of an array are returned as array scalars. That is, why arr[0,1] returns a np.float32 object, as opposed to a Python float.

It is not suggesting that we create an array scalar directly.

I first wrote this answer glossing over the difference between a 0d array, and what this quote is calling array scalars.



来源:https://stackoverflow.com/questions/49581213/is-there-a-better-way-to-assign-a-new-value-to-a-numpy-array-scalar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!