In [1]: data = np.array([[1,2,3], [4.0,5.0,6.0], [11,12,12.3]])
In [2]: dt = np.dtype({'names': ['1st', '2nd', '3rd'], 'formats':['f8','f8', 'f8']})
Your attempt:
In [3]: np.array(data,dt)
Out[3]:
array([[(1.0, 1.0, 1.0), (2.0, 2.0, 2.0), (3.0, 3.0, 3.0)],
[(4.0, 4.0, 4.0), (5.0, 5.0, 5.0), (6.0, 6.0, 6.0)],
[(11.0, 11.0, 11.0), (12.0, 12.0, 12.0), (12.3, 12.3, 12.3)]],
dtype=[('1st', '<f8'), ('2nd', '<f8'), ('3rd', '<f8')])
这段代码生成一个(3,3)的数组,每个元素都具有相同的值。在此情况下,data.astype(dt)
扮演着同样的角色。
但是,view
生成包含每个列数据的(3,1)数组。
In [4]: data.view(dt)
Out[4]:
array([[(1.0, 2.0, 3.0)],
[(4.0, 5.0, 6.0)],
[(11.0, 12.0, 12.3)]],
dtype=[('1st', '<f8'), ('2nd', '<f8'), ('3rd', '<f8')])
我需要提醒的是,view
只在所有字段与原始字段具有相同数据类型时才有效。它使用相同的数据缓冲区,仅以不同的方式解释值。
您可以将结果从 (3,1) 重塑为 (3,)。
但是,由于您想要 A['1st']
成为 [1,2,3]
- 一个 data
的行 - 我们必须进行其他操作。
In [16]: data.T.copy().view(dt)
Out[16]:
array([[(1.0, 4.0, 11.0)],
[(2.0, 5.0, 12.0)],
[(3.0, 6.0, 12.3)]],
dtype=[('1st', '<f8'), ('2nd', '<f8'), ('3rd', '<f8')])
In [17]: _['1st']
Out[17]:
array([[ 1.],
[ 2.],
[ 3.]])
我进行转置,然后复制(重新排列底层数据缓冲区)。现在一个视图将[1,2,3]
放在一个字段中。
请注意,结构化数组的显示使用()
而不是[]
表示“行”。这是提示它如何接受输入的线索。
我可以通过以下方式将您的data
转换为元组列表:
In [19]: [tuple(i) for i in data.T]
Out[19]: [(1.0, 4.0, 11.0), (2.0, 5.0, 12.0), (3.0, 6.0, 12.300000000000001)]
In [20]: np.array([tuple(i) for i in data.T],dt)
Out[20]:
array([(1.0, 4.0, 11.0), (2.0, 5.0, 12.0), (3.0, 6.0, 12.3)],
dtype=[('1st', '<f8'), ('2nd', '<f8'), ('3rd', '<f8')])
In [21]: _['1st']
Out[21]: array([ 1., 2., 3.])
这是一个包含3个字段的(3,)数组。
使用元组列表是向np.array(...,dt)
提供数据的常规方法。请参见我的评论中的文档链接。
您还可以创建一个空数组,逐行或逐个字段填充它。
In [26]: A=np.zeros((3,),dt)
In [27]: for i in range(3):
....: A[i]=data[:,i].copy()
没有使用 copy
我会收到一个错误提示 ValueError: ndarray is not C-contiguous
逐个填充字段:
In [29]: for i in range(3):
....: A[dt.names[i]]=data[i,:]
通常,结构化数组有许多行和少量字段。因此,按字段填充相对较快。这就是recarray
函数处理大多数复制任务的方式。
fromiter
也可以使用:
In [31]: np.fromiter(data, dtype=dt)
Out[31]:
array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0), (11.0, 12.0, 12.3)],
dtype=[('1st', '<f8'), ('2nd', '<f8'), ('3rd', '<f8')])
在不使用复制的情况下使用data.T
时出现的错误强烈表明正在进行逐行迭代(我的In[27])。
In [32]: np.fromiter(data.T, dtype=dt)
ValueError: ndarray is not C-contiguous
zip(*data)
是重新排列输入数组的另一种方式(请参见评论链接中 @unutbu 的答案)。
np.fromiter(zip(*data),dtype=dt)
正如评论中指出的那样,fromarrays
可以起作用:
np.rec.fromarrays(data,dt)
这是一个使用by field
复制方法的rec
函数示例:
arrayList = [sb.asarray(x) for x in arrayList]
....
_array = recarray(shape, descr)
for i in range(len(arrayList)):
_array[_names[i]] = arrayList[i]
在我们的情况下,这是指:
In [8]: data1 = [np.asarray(i) for i in data]
In [9]: data1
Out[9]: [array([ 1., 2., 3.]), array([ 4., 5., 6.]), array([ 11. , 12. , 12.3])]
In [10]: for i in range(3):
A[dt.names[i]] = data1[i]
np.rec.fromarrays
:a = np.rec.fromarray(data, dtype= {'names': ['1st', '2nd', '3rd'], 'formats':['f8','f8', 'f8']})
。这使得这个问题本质上成为了 http://stackoverflow.com/questions/8220689/how-to-make-a-structured-array-from-multiple-simple-array 的重复。 - user707650fromarray
改为fromarrays
。非常感谢! - xtlc