Radu Ionescu
Radu Ionescu

Reputation: 3532

List of tuples converted to numpy array

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

Answers (2)

mins
mins

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

hpaulj
hpaulj

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

Related Questions