1

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?

2 Answers 2

5

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'>]
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! nice and clean!
2

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')]

3 Comments

Thanks. It seems that numpy basic data structures persist. For example, type(tuple([tuple(i) for i in a])[0][0]) yields numpy.float64, but needs to be float (just native data type).
I forgot that there's a difference beteen list(a) and a.tolist(). The latter is a recursive converter. Try my edit.
I didn''t notice your answer when I made my additions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.