问题
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