Oleg Melnikov
Oleg Melnikov

Reputation: 3298

Convert arrays (of numpy data types) to tuples (of native data types) in Python

How can effectively I convert an array of arrays of numpy.float64 to tuple of tuples of float

Input is

a = array([array([1.]), array([2, 3]), array(['a', 'b', 'c'])])

where values are of numpy basic types, such as numpy.float64, numpy.int32, numpy.str_, etc.

Output is

((1.,), (2, 3), ('a', 'b', 'c'))

where values are of native type float, int, str, ...

I suppose there may be recursive and iterative approaches... Any ideas?

Upvotes: 1

Views: 3060

Answers (2)

hpaulj
hpaulj

Reputation: 231605

A list comprehension does the job nicely:

In [191]: a = np.array([np.array([1.]), np.array([2, 3]), np.array(['a', 'b', 'c'])])
In [192]: a
Out[192]: 
array([array([ 1.]), array([2, 3]),
       array(['a', 'b', 'c'], 
      dtype='<U1')], dtype=object)
In [193]: [tuple(i) for i in a]
Out[193]: [(1.0,), (2, 3), ('a', 'b', 'c')]
In [194]: tuple([tuple(i) for i in a])
Out[194]: ((1.0,), (2, 3), ('a', 'b', 'c))

Wrapping the list of arrays in another array layer doesn't do much. An array of dtype object is just a list with a ndarray wrapper. Most operations of a will treat it like a list.

In [195]: ll=[np.array([1.]), np.array([2, 3]), np.array(['a', 'b', 'c'])]In [196]: ll
Out[196]: 
[array([ 1.]), array([2, 3]), array(['a', 'b', 'c'], 
       dtype='<U1')]
In [197]: [tuple(l) for l in ll]
Out[197]: [(1.0,), (2, 3), ('a', 'b', 'c')]

correction - we need to use tolist() first if we want to convert the elements of the inner arrays. tuple(i) is like list(i), iterating on the 1st dimension, while i.tolist() does a recursive conversion.

In [204]: type([tuple(i.tolist()) for i in a][0][0])
Out[204]: float

More on the difference between list and tolist when we apply them to a 2d array:

In [210]: np.ones((2,3)).tolist()
Out[210]: [[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]]
In [211]: list(np.ones((2,3)))
Out[211]: [array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.])]
In [212]: tuple(np.ones((2,3)))
Out[212]: (array([ 1.,  1.,  1.]), array([ 1.,  1.,  1.]))

There isn't a totuple() method, and nothing quick and easy that would convert a nested lists of lists to a nested tuple of tuples.

tolist does not recurse through the dtype=object layer:

In [214]: a.tolist()
Out[214]: 
[array([ 1.]), array([2, 3]), array(['a', 'b', 'c'], 
       dtype='<U1')]

Upvotes: 2

DSM
DSM

Reputation: 353419

Having a numpy array of arrays of different sizes and types is usually a sign something's gone wrong in your design. But if you've got that for some reason, you can use .tolist() to convert a numpy array to a list and simultaneously change the types to Python-native ones. For example:

>>> a = array([array([1.]), array([2, 3]), array(['a', 'b', 'c'])])
>>> a
array([array([ 1.]), array([2, 3]),
       array(['a', 'b', 'c'], 
      dtype='<U1')], dtype=object)
>>> t = tuple(tuple(x.tolist()) for x in a)
>>> t
((1.0,), (2, 3), ('a', 'b', 'c'))

where we had

>>> [type(x[0]) for x in a]
[<class 'numpy.float64'>, <class 'numpy.int32'>, <class 'numpy.str_'>]

but now have

>>> [type(x[0]) for x in t]
[<class 'float'>, <class 'int'>, <class 'str'>]

Upvotes: 4

Related Questions