Reputation: 3532
I have a list of tuples, one of them is an object and the other one is generic. When I run np.asarray(list_in)
the result is a 2D array, with the tuples being converted in a row. However I would like to obtain a 1D array made of tuples.
I could pass a dtype
to force it and it works well if I try this minimalistic example
a = [(1,2),(3,4)]
b = np.asarray(a,dtype=('float,float'))
print b
[( 1., 2.) ( 3., 4.)]
But how do I take the first element of the list and construct a proper dtype
out of it. type(list_in[0])
returns tuple
and passing this to asarray does not work.
Upvotes: 3
Views: 10072
Reputation: 7494
I have a list of tuples, one of them is an object and the other one is generic. When I run np.asarray(list_in) the result is a 2D array, with the tuples being converted in a row. However I would like to obtain a 1D array made of tuples.
In short
If you have a list of tuples of anything like tuples (str
, tuple
):
tuples = [('a', (-2.56, -1.79)),
('b', (-1.79, -1.02)),
('c', (-1.02, -0.26)),
('d', (-0.26, 0.51)),
('e', (0.51, 1.28))]
and want to create a 1D array of tuples, use a dtype
describing your tuples as object
sequences:
a = np.array(tuples, dtype='object, object')
The 1D array will have the void
type, but the elements will be tuples with preserved types for their own elements:
a[n].
--> type numpy.void
a[n][0]
--> type str
a[n][1]
--> type tuple
Recovering the initial list:
print(list(a))
[('a', (-2.56, -1.79)),
('b', (-1.79, -1.02)),
('c', (-1.02, -0.26)),
('d', (-0.26, 0.51)),
('e', (0.51, 1.28))]
Experiment
import numpy as np
tuples = [('a', (-2.56, -1.79)),
('b', (-1.79, -1.02)),
('c', (-1.02, -0.26)),
('d', (-0.26, 0.51)),
('e', (0.51, 1.28))]
a = np.array(tuples, dtype='object, object')
print(f'a shape: {a.shape}')
print(f'a dtype: {a.dtype}')
i = 3
t = a[i]
print(f'a[{i}]: {t}, type: {type(t)}')
for e in t:
print(f'Type of {e}: {type(e)}')
a shape: (5,)
a dtype: [('f0', 'O'), ('f1', 'O')]
a[3]: ('d', (-0.26, 0.51)), type: <class 'numpy.void'>
Type of d: <class 'str'>
Type of (-0.26, 0.51): <class 'tuple'>
Upvotes: 0
Reputation: 231335
With this list of tuples you can make 3 kinds of arrays:
In [420]: a = [(1,2),(3,4)]
2d array, with dtype inferred from the inputs (but it could also be specified as something like float). Inputs match in size.
In [421]: np.array(a)
Out[421]:
array([[1, 2],
[3, 4]])
Structured array. 1d with 2 fields. Field indexing by name. Input must be a list of tuples (not list of lists):
In [422]: np.array(a, dtype='i,i')
Out[422]:
array([(1, 2), (3, 4)],
dtype=[('f0', '<i4'), ('f1', '<i4')])
In [423]: _['f0']
Out[423]: array([1, 3], dtype=int32)
In the structured array, input and display uses tuples, but the data is not actually stored as tuples. The values are packed as bytes - in this case 8 bytes representing 2 integers.
Object array. This is 1d with tuple contents. Contents could be anything else. This is an enhanced/debased list.
In [424]: A = np.empty((2,), dtype=object)
In [425]: A[:] = a
In [426]: A
Out[426]: array([(1, 2), (3, 4)], dtype=object)
In [427]: A.shape
Out[427]: (2,)
In [428]: A[1]
Out[428]: (3, 4)
Out[428]
is an actual tuple. Trying to modify it, A[1][0]=30
, raises an error.
In this last case A = np.empty(2, dtype=tuple)
does the same thing. Any thing other than integer, float, string, etc is 'converted' to `object'.
Simply specifying object dtype doesn't help. The result is 2d with numeric elements (but stored as object pointers).
In [429]: np.array(a, dtype=object)
Out[429]:
array([[1, 2],
[3, 4]], dtype=object)
In [430]: _.shape
Out[430]: (2, 2)
More on making an object dtype array at
numpy ravel on inconsistent dimensional object
Upvotes: 7