简体   繁体   中英

How to change the dtype of a ndarray to custom one in numpy?

I made a dtype that is:

mytype = np.dtype([('a',np.uint8), ('b',np.uint8), ('c',np.uint8)])

so the array using this dtype:

test1 = np.zeros(3, dtype=mytype)

test1 is:

array([(0, 0, 0), (0, 0, 0), (0, 0, 0)],
      dtype=[('a', '|u1'), ('b', '|u1'), ('c', '|u1')])

Now I have test2:

test2 = np.array([[1,2,3], [4,5,6], [7,8,9]])

When I use test2.astype(mytype) , the result is not what I want to be:

array([[(1, 1, 1), (2, 2, 2), (3, 3, 3)],
       [(4, 4, 4), (5, 5, 5), (6, 6, 6)],
       [(7, 7, 7), (8, 8, 8), (9, 9, 9)]],
      dtype=[('a', '|u1'), ('b', '|u1'), ('c', '|u1')])

I want the result to be:

array([(1, 2, 3), (4, 5, 6), (7, 8, 9)],
      dtype=[('a', '|u1'), ('b', '|u1'), ('c', '|u1')])

Is there any way? Thanks.

You can use the fromarrays method of numpy.core.records (see documentation ):

np.rec.fromarrays(test2.T, mytype)
Out[13]: 
rec.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], 
      dtype=[('a', '|u1'), ('b', '|u1'), ('c', '|u1')])

The array has to be transposd first because the functions regards the rows of the array as the columns of the structured array in the output. See also this question: Converting a 2D numpy array to a structured array

Because all the fields are the same type, you can also use:

>>> test2.astype(np.uint8).view(mytype).squeeze(axis=-1)
array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], 
      dtype=[('a', 'u1'), ('b', 'u1'), ('c', 'u1')])

The squeeze is needed because test2 is 2d, but you wanted a 1d result

When creating the array, if the input iterable contains tuples (which are guaranteed to be immutable) instead of lists (which are guaranteed not to be) then it will automatically take the input in the way you desire so long as the number of items in each tuple equals the number of fields in the structure:

In[7]: test2 = np.array([(1,2,3), (4,5,6), (7,8,9)], dtype = mytype)

In[8]: test2
Out[8]: 
array([(1, 2, 3), (4, 5, 6), (7, 8, 9)],
      dtype=[('a', 'u1'), ('b', 'u1'), ('c', 'u1')])

There is no need to go to np.rec etc for just this. If however the input iterable contains lists and not tuples, then numpy doesn't take the fields one for one as you expect and does the data duplication.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM