gerrit
gerrit

Reputation: 26465

How do I write to multiple fields of a structured array?

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

Answers (2)

askewchan
askewchan

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:

Record Access

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 type x.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 a FutureWarning 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. use x[[‘field-name1’,’field-name2’]].copy(). This will work with both past and future versions of NumPy.

Upvotes: 1

gg349
gg349

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

Related Questions