2
import numpy as np
arr = np.array([(1,2), (3,4)], dtype=[('c1', float), ('c2', float)])
arr += 3

results in an invalid type promotion error. Is there a way I can have nice labeled columns like a structured array, but still be able to do operations like it's a simple dtype=float array?

Alternatively, is there an easy way to cast a dtype=float array into a structured array? i.e.

arr = np.array([(1,2), (3,4)], dtype=float)
arr_struc = arr.astype([('c1', float), ('c2', float)])

only where it doesn't broadcast and matches columns to names. Seems like I shouldn't have to do this loop:

arr_struc = np.zeros(2, dtype=[('c1', float), ('c2', float)])
for i,key in enumerate(arr_struc.dtype.names):  arr_struc[key] = arr[i,:]
3
  • On the structured array docs page, they describe the numpy.lib.recfunctions module. In has a structured_to_unstructured and unstructured_to_structured functions. A view if it works is faster, but these are more general purpose. Commented Jun 24, 2020 at 3:07
  • A key thing to keep in mind when doing your own conversion is that data for a structured array is in the form of a list of tuples, while unstructured displays as list of lists. But using structured arrays just to have pretty 'column' names is, I think, more work than its worth. Structured arrays are best when fields have distinct dtypes, esp. some numeric, and others string. Commented Jun 24, 2020 at 3:09
  • 1
    Yes, just use a .view again, see my edit Commented Jun 24, 2020 at 3:22

1 Answer 1

2

Hmmm. One option, use a view for this:

>>> import numpy as np
>>> arr = np.array([(1,2), (3,4)], dtype=[('c1', float), ('c2', float)])
>>> view = arr.view(float)
>>> view += 3
>>> arr
array([(4., 5.), (6., 7.)], dtype=[('c1', '<f8'), ('c2', '<f8')])
>>> view
array([4., 5., 6., 7.])

Not the cleanest. But it's a solution.

EDIT:

Yes, don't use astype use a view again:

>>> arr = np.array([(1,2), (3,4)], dtype=float)
>>> arr
array([[1., 2.],
       [3., 4.]])
>>> struct = arr.view(dtype=[('c1', float), ('c2', float)])
>>> struct
array([[(1., 2.)],
       [(3., 4.)]], dtype=[('c1', '<f8'), ('c2', '<f8')])
>>> struct.shape
(2, 1)

You may have to reshape it to your liking:

>>> struct.squeeze()
array([(1., 2.), (3., 4.)], dtype=[('c1', '<f8'), ('c2', '<f8')])
Sign up to request clarification or add additional context in comments.

2 Comments

That's a good way. I guess for my purposes I could also do most of the math on the float array, then convert it at the end. Is there an elegant way to do that (i.e., without a loop)? arr.astype([('c1', '<f8'), ('c2', '<f8')]) doesn't behave like I'd want.
@I.P.Freeley I don't follow, can you edit your question and elaborate?

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.