17

How do I convert the numpy record array below:

recs = [('Bill', 31, 260.0), ('Fred', 15, 145.0)]
r = rec.fromrecords(recs, names='name, age, weight', formats='S30, i2, f4')

to a list of dictionary like:

[{'name': 'Bill', 'age': 31, 'weight': 260.0}, 
'name': 'Fred', 'age': 15, 'weight': 145.0}]

4 Answers 4

23

I am not sure there is built-in function for that or not, but following could do the work.

>>> [dict(zip(r.dtype.names,x)) for x  in r]
[{'age': 31, 'name': 'Bill', 'weight': 260.0}, 
{'age': 15, 'name': 'Fred', 'weight': 145.0}]
Sign up to request clarification or add additional context in comments.

2 Comments

Probably worth pulling r.dtype.names out to a local variable. Possibly izip is faster than zip as the number of records increases
This will only work for a one-dimensional array, not for zero-dimensional ones or multi-dimensional ones. It is also not recursive, but numpy structs can contain more structs or arrays
2

Here's a solution that works in the following cases not covered by the other answers:

  • 0-dimensional arrays (scalars). e.g. np.array((1, 2), dtype=[('a', 'float32'), ('b', 'float32')])
  • elements of type np.void (result of indexing a record array)
  • multi-dimensional arrays of structs
  • structs containing structs, (e.g. structured_to_dict(np.zeros((), dtype=[('a', [('b', 'float32', (2,))])])))
  • Combinations of any of the above.
def structured_to_dict(arr: np.ndarray):
    import numpy as np

    if np.ndim(arr) == 0:
        if arr.dtype.names == None:
            return arr.item()
        # accessing by int does *not* work when arr is a zero-dimensional array!
        return {k: structured_to_dict(arr[k]) for k in arr.dtype.names}
    return [structured_to_dict(v) for v in arr]

2 Comments

Is structured_to_debug_dict supposed to be structured_to_dict?
Excellent. This appears to be a robust solution. Very useful with scipy.io.loadmat(file_name, squeeze_me=True).
1

This depends on the final structure required. This example shows a numpy recarray composed of several 1D subsets. To have a python dictionary instead, a possible conversion is:

import numpy as np

a = np.rec.array([np.array([1,3,6]), np.array([3.4,4.2,-1.2])], names=['t', 'x'])

b = {name:a[name] for name in a.dtype.names}

Comments

-2

Answered at Numpy-discussion by Robert Kern


Copy of concluding email from that discussion:

How do I convert the numpy record array below: recs = [('Bill', 31, 260.0), ('Fred', 15, 145.0)] r = rec.fromrecords(recs, names='name, age, weight', formats='S30, i2, f4') to a list of dictionary like: [{'name': 'Bill', 'age': 31, 'weight': 260.0}, 'name': 'Fred', 'age': 15, 'weight': 145.0}]

Assuming that your record array is only 1D:

In [6]: r.dtype.names Out[6]: ('name', 'age', 'weight')

In [7]: names = r.dtype.names

In [8]: [dict(zip(names, record)) for record in r] Out[8]: [{'age': 31, 'name': 'Bill', 'weight': 260.0}, {'age': 15, 'name': 'Fred', 'weight': 145.0}]

3 Comments

-1, link only answers are strongly discouraged on SO. If the link rots, then this answer becomes worse than not existing: maddening.
The link is gone already. A summary of the discussion would be great
The link's not gone, or was only temporarily gone. Downvoted answer, but added copy of the discussion conclusion in this answer. Which is the same solution as YOU's answer.

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.