1

I have structured numpy array of branched (i.e. some fields contain subfields) data type dtype, as shown here:

import numpy
dtype_sub = [('sub0', 'i4'), ('sub1', 'f8')]
dtype = [('info', [('field0', dtype_sub, 3),
                  ('field1', dtype_sub, 3)])]
array = [(tuple([[(0, 0.0) for j in range(3)] for i in range(2)]),)]
narray = numpy.array(array, dtype = dtype)

Everything works fine during the generation and accessing all the fields. Then I try to replace one of the fields with new values. However, this does not work:

field0_new = [(1, 1.0) for i in range(3)]
print('--- Original field0: ---')
print(narray[0]['info']['field0'])
print('--- To replace with: ---')
print(field0_new)
narray[0]['info']['field0'] = field0_new
print('--- Replaced field0: ---')
print(narray[0]['info']['field0'])

outputs

--- Original field0: ---
[(0, 0.0) (0, 0.0) (0, 0.0)]
--- To replace with: ---
[(1, 1.0), (1, 1.0), (1, 1.0)]
Traceback (most recent call last):
  File "test.py", line 12, in <module>
    narray[0]['info']['field0'] = field0_new
ValueError: cannot copy sequence with size 2 to array axis with dimension 3

I got confused a little bit, as replacing of a larger field, which contains the one that I want to replace, works fine:

info_new = [[(1, 1.0) for j in range(3)] for i in range(2)]
print('--- Original info: ---')
print(narray[0]['info'])
print('--- To replace with: ---')
print(info_new)
narray[0]['info'] = info_new
print('--- Replaced info: ---')
print(narray[0]['info'])

outputs

--- Original info: ---
([(0, 0.0), (0, 0.0), (0, 0.0)], [(0, 0.0), (0, 0.0), (0, 0.0)])
--- To replace with: ---
[[(1, 1.0), (1, 1.0), (1, 1.0)], [(1, 1.0), (1, 1.0), (1, 1.0)]]
--- Replaced info: ---
([(1, 1.0), (1, 1.0), (1, 1.0)], [(1, 1.0), (1, 1.0), (1, 1.0)])

I noticed that in one case there are commas inside list in the printed representation of the field ([(0, 0.0), (0, 0.0), (0, 0.0)]), while in the other there are no commas ([(0, 0.0) (0, 0.0) (0, 0.0)]). However, I cannot understand this, as they are supposed to be representations of the same field.

Can anyone help with this issue?

Edit:

After playing a bit around I noticed that there is double meaning for passing tuples and lists to a complex structured array:

info_new = [[(i * j, 10.5 + j) for j in range(3)] for i in range(2)]

leads to incorrect

--- To replace with: ---
[[(0, 10.5), (0, 11.5), (0, 12.5)], [(0, 10.5), (1, 11.5), (2, 12.5)]]
--- Replaced info: ---
([(0, 0.0), (0, 0.0), (0, 0.0)], [(10, 10.5), (10, 10.5), (10, 10.5)])

and

info_new = tuple([[(i * j, 10.5 + j) for j in range(3)] for i in range(2)])

outputs expectedly

--- To replace with: ---
([(0, 10.5), (0, 11.5), (0, 12.5)], [(0, 10.5), (1, 11.5), (2, 12.5)])
--- Replaced info: ---
([(0, 10.5), (0, 11.5), (0, 12.5)], [(0, 10.5), (1, 11.5), (2, 12.5)])

However, I still cannot understand, how the syntax works and also why direct replacing of field0 does not work.

Edit 2:

Currently I came up with 2 own ideas (plus answer of Warren Weckesser ):

1) Pass it as part of a larger field:

info_new = tuple([field0_new, narray[0]['info']['field1']])
narray[0]['info'] = info_new

2) Pass it in parts:

for i in range(len(narray[0]['info']['field0'])):
    narray[0]['info']['field0'][i] = field0_new[i]

Nevertheless, all these solutions are quite sloppy and not universal.

Still waiting for a proper answer with the syntax ambiguity explanation.

1 Answer 1

1

It works if you index the fields first, then the array sequence:

narray['info']['field0'][0] = field0_new

(A better answer would investigate why, but's that's all I got at the moment.)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.