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.