array of tuples
can have several meanings.
The double iteration produces a nested list of tuples:
In [292]: alist = [[(i,j) for j in y] for i in x]
In [293]: alist
Out[293]:
[[(0, 0), (0, 1), (0, 2), (0, 3)],
[(1, 0), (1, 1), (1, 2), (1, 3)],
[(2, 0), (2, 1), (2, 2), (2, 3)],
[(3, 0), (3, 1), (3, 2), (3, 3)]]
The default way of making an array from this produces a 3d array containing integer elements
In [294]: arr=np.array(alist)
In [295]: arr.dtype
Out[295]: dtype('int32')
In [296]: arr.shape
Out[296]: (4, 4, 2)
In [297]: arr[0,0]
Out[297]: array([0, 0])
Defining a compound dtype creates a structured array:
In [298]: arr=np.array(alist,'i,i')
In [299]: arr.dtype
Out[299]: dtype([('f0', '<i4'), ('f1', '<i4')])
In [300]: arr.shape
Out[300]: (4, 4)
In [301]: arr
Out[301]:
array([[(0, 0), (0, 1), (0, 2), (0, 3)],
[(1, 0), (1, 1), (1, 2), (1, 3)],
[(2, 0), (2, 1), (2, 2), (2, 3)],
[(3, 0), (3, 1), (3, 2), (3, 3)]],
dtype=[('f0', '<i4'), ('f1', '<i4')])
arr.tolist()
looks just like alist
.
An element of this array is not a tuple, though it does display as such. I prefer to call it a record.
In [303]: type(arr[0,0])
Out[303]: numpy.void
In [304]: arr[0,0]
Out[304]: (0, 0)
The 2 elements of these records are fields, and can be accessed by name, e.g. arr['f0'], arr['f1']
, which will both be 2d integer arrays.
It is possible to create a object array that can contain literal tuples (actually pointers to tuples elsewhere in memory:
In [305]: arr = np.empty((4,4),object)
In [306]: arr
Out[306]:
array([[None, None, None, None],
[None, None, None, None],
[None, None, None, None],
[None, None, None, None]], dtype=object)
In [307]: arr[...]=alist
In [308]: arr
Out[308]:
array([[(0, 0), (0, 1), (0, 2), (0, 3)],
[(1, 0), (1, 1), (1, 2), (1, 3)],
[(2, 0), (2, 1), (2, 2), (2, 3)],
[(3, 0), (3, 1), (3, 2), (3, 3)]], dtype=object)
In [309]: type(arr[0,0])
Out[309]: tuple
A non-iterative way of constructing an array from these x,y variables is meshgrid
, which returns a list of (4,4) arrays. They can be 'stacked' in a way that matches the (4,4,2) array:
In [322]: I,J = np.meshgrid(x,y,indexing='ij')
In [323]: np.allclose(np.stack((I,J),axis=2), np.array(alist))
Out[323]: True
We can construct the record array from these as well:
In [327]: arr = np.zeros((4,4),'i,i')
In [328]: arr['f0']=I
In [329]: arr['f1']=J