I have a 2D numpy array with elements of the type np.void
that are essentially tuples. Is there an efficient way to unpack the values in these tuples to a 3rd dime
In [601]: a = np.array([[(1, 2, 3), (1, 2, 3), (1, 2, 3)],
...: [(1, 2, 3), (1, 2, 3), (1, 2, 3)],
...: [(1, 2, 3), (1, 2, 3), (1, 2, 3)]],
...: dtype=[('B4', '<u2'), ('B3', '<u2'), ('B2', '<u2')])
In [602]: a.dtype
Out[602]: dtype([('B4', '<u2'), ('B3', '<u2'), ('B2', '<u2')])
In [603]: a.shape
Out[603]: (3, 3)
This is a structured array, with a compound dtype. The tuples display individual elements of the 2d array.
Recent numpy versions have added a function to conveniently convert structured arrays to unstructured:
In [606]: b=rf.structured_to_unstructured(a)
In [607]: b
Out[607]:
array([[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]]], dtype=uint16)
In [608]: b[:,:,1]
Out[608]:
array([[2, 2, 2],
[2, 2, 2],
[2, 2, 2]], dtype=uint16)
a
has 3 fields. Individual fields can be accessed by name:
In [610]: a['B4']
Out[610]:
array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]], dtype=uint16)
That means you could construct the 3d array by concatenating the 3 individual fields:
np.stack([a['B4'],a['B3'],a['B2']])
This is like your last solution, but without the i,j
iteration.
The view
approach in the other answer works in this case because all fields have the same dtype
, <u2
. That means the same underlying data can be viewed as individual <u2
elements, or a groups of 3 of these.
import numpy.lib.recfunctions as rf
The rf.structured_to_unstructured
works in more general cases where view
does not, such as a mix of dtypes, (e.g. floats and integers).
You can view as a standard numpy
array to allow for the indexing you're after.
b = a.view('(3,)<u2')
array([[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3],
[1, 2, 3]]], dtype=uint16)
>>> b.shape
(3, 3, 3)
>>> b[:, :, 0]
array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]], dtype=uint16)