Reputation: 26465
I have an nd-array with names fields as below. I'm trying to assign values to multiple fields at once, but it seems to have no effect at all. See the example below:
In [380]: A = numpy.zeros(dtype=[("A", "f8"), ("B", "f8"), ("C", "f8")], shape=(5,))
In [381]: A[["A", "B", "C"]][0] = (2, 3, 4)
I would expect that now, these values are assigned to A
, but in fact, the array is still all-zero:
In [382]: A[0]
Out[382]: (0.0, 0.0, 0.0)
When I index the other way around, I get an IndexError
; (A[0]["A"]
works, but A[0][["A", "B", "C"]]
is IndexError
:
In [383]: A[0][["A", "B", "C"]] = (2, 3, 4)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-383-9b5cca19867a> in <module>()
----> 1 A[0][["A", "B", "C"]] = (2, 3, 4)
IndexError: invalid index
Why does A[fieldnames][0] = values
not assign anything? Why does A[0][fieldnames]
fail with an IndexError
? How can I write multiple values at once to a structured array (apart from looping explicitly)?
Upvotes: 2
Views: 1086
Reputation: 46530
If you really want to set all three fields, as you show in your example, you can simply just select the first entry:
A[0] = 2, 3, 4
In the other case (like A[['A','B']][0] = 2, 3
) this might help you understand a little:
FutureWarning: Numpy has detected that you (may be) writing to an array returned
by numpy.diagonal or by selecting multiple fields in a record
array. This code will likely break in a future numpy release --
see numpy.diagonal or arrays.indexing reference docs for details.
The quick fix is to make an explicit copy (e.g., do
arr.diagonal().copy() or arr[['f0','f1']].copy()).
This will probably be made easier in future versions of numpy, because indexing with several fields will soon return a view:
If the ndarray object is a record array, i.e. its data type is a record data type, the fields of the array can be accessed by indexing the array with strings, dictionary-like.
Indexing
x['field-name']
returns a new view to the array, which is of the same shape as x (except when the field is a sub-array) but of data typex.dtype['field-name']
and contains only the part of the data in the specified field. Also record array scalars can be “indexed” this way.Indexing into a record array can also be done with a list of field names, e.g.
x[['field-name1','field-name2']]
. Currently this returns a new array containing a copy of the values in the fields specified in the list. As of NumPy 1.7, returning a copy is being deprecated in favor of returning a view. A copy will continue to be returned for now, but aFutureWarning
will be issued when writing to the copy. If you depend on the current behavior, then we suggest copying the returned array explicitly, i.e. usex[[‘field-name1’,’field-name2’]].copy()
. This will work with both past and future versions of NumPy.
Upvotes: 1
Reputation: 22681
A[fieldnames][0] = values
assigns nothing because you are assigning the value to a copy of the array, returned by A[fieldnames]
.
A[0][["A", "B", "C"]]
fails because as the message says ["A", "B", "C"]
is an invalid index. You want to use A[0]=2,3,4
.
Upvotes: 0