如何在numpy中将ndarray的dtype更改为自定义类型?

4 投票
3 回答
1318 浏览
提问于 2025-04-17 03:37

我创建了一种数据类型(dtype),它是:

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

所以使用这种数据类型的数组是:

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

test1 是:

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

现在我有了 test2:

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

当我使用 test2.astype(mytype) 时,结果并不是我想要的:

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

我希望结果是:

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

有没有什么办法可以做到?谢谢。

3 个回答

0

在创建数组的时候,如果你输入的是元组(元组是不可改变的)而不是列表(列表是可以改变的),那么只要每个元组里的元素数量和你想要的结构中的字段数量一致,程序就会自动按照你想要的方式来处理这些输入。

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

为了这个目的,你不需要去使用 np.rec 等其他复杂的东西。不过,如果你输入的是列表而不是元组,那么numpy就不会像你期待的那样一一对应字段,而是会复制数据。

0

因为所有的字段都是相同类型的,所以你也可以这样做:

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

这里需要用到“挤压”这个操作,因为 test2 是二维的,但你想要的是一维的结果。

5

你可以使用numpy.core.records里的fromarrays方法(具体可以查看文档):

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

在使用之前,数组需要先进行转置,因为这个函数会把数组的行当作输出中结构化数组的列。你也可以看看这个问题:将二维numpy数组转换为结构化数组

撰写回答