Python 将二维numpy数组转换为结构化数组

Python 将二维numpy数组转换为结构化数组,python,numpy,Python,Numpy,我正在尝试将二维数组转换为具有命名字段的结构化数组。我希望2D数组中的每一行都是结构化数组中的新记录。不幸的是,我所做的一切都没有达到我预期的效果 我从以下几点开始: >>> myarray = numpy.array([("Hello",2.5,3),("World",3.6,2)]) >>> print myarray [['Hello' '2.5' '3'] ['World' '3.6' '2']] 我想转换为如下所示的内容: >>>

我正在尝试将二维数组转换为具有命名字段的结构化数组。我希望2D数组中的每一行都是结构化数组中的新记录。不幸的是,我所做的一切都没有达到我预期的效果

我从以下几点开始:

>>> myarray = numpy.array([("Hello",2.5,3),("World",3.6,2)])
>>> print myarray
[['Hello' '2.5' '3']
 ['World' '3.6' '2']]
我想转换为如下所示的内容:

>>> newarray = numpy.array([("Hello",2.5,3),("World",3.6,2)], dtype=[("Col1","S8"),("Col2","f8"),("Col3","i8")])
>>> print newarray
[('Hello', 2.5, 3L) ('World', 3.6000000000000001, 2L)]
我所尝试的:

>>> newarray = myarray.astype([("Col1","S8"),("Col2","f8"),("Col3","i8")])
>>> print newarray
[[('Hello', 0.0, 0L) ('2.5', 0.0, 0L) ('3', 0.0, 0L)]
 [('World', 0.0, 0L) ('3.6', 0.0, 0L) ('2', 0.0, 0L)]]

>>> newarray = numpy.array(myarray, dtype=[("Col1","S8"),("Col2","f8"),("Col3","i8")])
>>> print newarray
[[('Hello', 0.0, 0L) ('2.5', 0.0, 0L) ('3', 0.0, 0L)]
 [('World', 0.0, 0L) ('3.6', 0.0, 0L) ('2', 0.0, 0L)]]
这两种方法都试图将myarray中的每个条目转换为具有给定数据类型的记录,因此插入额外的零。我不知道如何让它将每一行转换成一条记录

另一次尝试:

>>> newarray = myarray.copy()
>>> newarray.dtype = [("Col1","S8"),("Col2","f8"),("Col3","i8")]
>>> print newarray
[[('Hello', 1.7219343871178711e-317, 51L)]
 [('World', 1.7543139673493688e-317, 50L)]]
这一次不执行实际转换。内存中的现有数据只是重新解释为新的数据类型

我开始使用的数组是从文本文件读入的。数据类型在创建之前是未知的,因此我无法在创建时设置数据类型。我需要一个高性能和优雅的解决方案,将工作在一般情况下,因为我会做这种类型的转换很多,很多次为各种各样的应用

谢谢

您可以使用以下方法“从(平面)数组列表创建记录数组”:

>>> import numpy as np
>>> myarray = np.array([("Hello",2.5,3),("World",3.6,2)])
>>> print myarray
[['Hello' '2.5' '3']
 ['World' '3.6' '2']]


>>> newrecarray = np.core.records.fromarrays(myarray.transpose(), 
                                             names='col1, col2, col3',
                                             formats = 'S8, f8, i8')

>>> print newrecarray
[('Hello', 2.5, 3) ('World', 3.5999999046325684, 2)]

我试着做类似的事情。我发现,当numpy从现有的2D数组(使用np.core.records.fromArray)创建结构化数组时,它将2D数组中的每一列(而不是每一行)视为一条记录。所以你必须转置它。numpy的这种行为似乎不是很直观,但可能有一个很好的理由。

好吧,我已经为此奋斗了一段时间,但我找到了一种不需要太多努力的方法。如果这个代码是“脏的”,我道歉

让我们从二维阵列开始:

mydata = numpy.array([['text1', 1, 'longertext1', 0.1111],
                     ['text2', 2, 'longertext2', 0.2222],
                     ['text3', 3, 'longertext3', 0.3333],
                     ['text4', 4, 'longertext4', 0.4444],
                     ['text5', 5, 'longertext5', 0.5555]])
因此,我们最终得到一个4列5行的二维数组:

mydata.shape
Out[30]: (5L, 4L)
要使用numpy.core.records.arrays,我们需要提供输入参数作为数组列表,以便:

tuple(mydata)
Out[31]: 
(array(['text1', '1', 'longertext1', '0.1111'], 
      dtype='|S11'),
 array(['text2', '2', 'longertext2', '0.2222'], 
      dtype='|S11'),
 array(['text3', '3', 'longertext3', '0.3333'], 
      dtype='|S11'),
 array(['text4', '4', 'longertext4', '0.4444'], 
      dtype='|S11'),
 array(['text5', '5', 'longertext5', '0.5555'], 
      dtype='|S11'))
这会为每行数据生成一个单独的数组,但我们需要按列显示输入数组,因此我们需要:

tuple(mydata.transpose())
Out[32]: 
(array(['text1', 'text2', 'text3', 'text4', 'text5'], 
      dtype='|S11'),
 array(['1', '2', '3', '4', '5'], 
      dtype='|S11'),
 array(['longertext1', 'longertext2', 'longertext3', 'longertext4',
       'longertext5'], 
      dtype='|S11'),
 array(['0.1111', '0.2222', '0.3333', '0.4444', '0.5555'], 
      dtype='|S11'))
最后,它需要是数组列表,而不是元组,因此我们将上面的内容包装在list()中,如下所示:

list(tuple(mydata.transpose()))
这是我们的数据输入参数。。。。接下来是数据类型:

mydtype = numpy.dtype([('My short text Column', 'S5'),
                       ('My integer Column', numpy.int16),
                       ('My long text Column', 'S11'),
                       ('My float Column', numpy.float32)])
mydtype
Out[37]: dtype([('My short text Column', '|S5'), ('My integer Column', '<i2'), ('My long text Column', '|S11'), ('My float Column', '<f4')])
。。。祝你好运:

myRecord
Out[36]: 
rec.array([('text1', 1, 'longertext1', 0.11110000312328339),
       ('text2', 2, 'longertext2', 0.22220000624656677),
       ('text3', 3, 'longertext3', 0.33329999446868896),
       ('text4', 4, 'longertext4', 0.44440001249313354),
       ('text5', 5, 'longertext5', 0.5554999709129333)], 
      dtype=[('My short text Column', '|S5'), ('My integer Column', '<i2'), ('My long text Column', '|S11'), ('My float Column', '<f4')])
我希望这能有所帮助,因为我浪费了太多时间在numpy.asarray和mydata.astype等上,试图在最终制定出这个方法之前实现它。

我想

new_array = np.core.records.fromrecords([("Hello",2.5,3),("World",3.6,2)],
                                        names='Col1,Col2,Col3',
                                        formats='S8,f8,i8')

是您想要的。

如果数据以元组列表开始,那么创建结构化数组是很简单的:

In [228]: alist = [("Hello",2.5,3),("World",3.6,2)]
In [229]: dt = [("Col1","S8"),("Col2","f8"),("Col3","i8")]
In [230]: np.array(alist, dtype=dt)
Out[230]: 
array([(b'Hello',  2.5, 3), (b'World',  3.6, 2)], 
      dtype=[('Col1', 'S8'), ('Col2', '<f8'), ('Col3', '<i8')])
zip
方便地为我们提供了一个元组列表。现在,我们可以使用所需的数据类型重新创建阵列:

In [235]: np.array(_, dtype=dt)
Out[235]: 
array([(b'Hello',  2.5, 3), (b'World',  3.6, 2)], 
      dtype=[('Col1', 'S8'), ('Col2', '<f8'), ('Col3', '<i8')])
在内部,
fromArray
采用一种常见的
recfunctions
方法:创建目标数组,并按字段名复制值。实际上,它做到了:

In [237]: newarr = np.empty(arr.shape[0], dtype=dt)
In [238]: for n, v in zip(newarr.dtype.names, arr.T):
     ...:     newarr[n] = v
     ...:     
In [239]: newarr
Out[239]: 
array([(b'Hello',  2.5, 3), (b'World',  3.6, 2)], 
      dtype=[('Col1', 'S8'), ('Col2', '<f8'), ('Col3', '<i8')])
[237]中的
:newarr=np.empty(arr.shape[0],dtype=dt)
In[238]:对于n,v在zip中(newarr.dtype.names,arr.T):
…:newarr[n]=v
...:     
在[239]中:newarr
出[239]:
数组([(b'Hello',2.5,3),(b'World',3.6,2)],

dtype=[('Col1','S8'),('Col2','在“记录数组”和“结构化数组”之间有很多混淆。下面是我对结构化数组的简短解决方案

dtype = np.dtype([("Col1","S8"),("Col2","f8"),("Col3","i8")])
myarray = np.array([("Hello",2.5,3),("World",3.6,2)], dtype=dtype)
np.array(np.rec.fromarrays(myarray.transpose(), names=dtype.names).astype(dtype=dtype).tolist(), dtype=dtype)

因此,假设定义了
dtype
,这是一个单行程序。

使用
fromrecords
可以避免
transpose()
这会创建一个记录数组,而不是结构化的数据数组。这会生成一个记录数组(
np.recarray
),而不是一个结构化数组(
np.ndarray
)。还有一个替代文件记录在:“recarray=myarray.view(dtype=((np.record,myarray.dtype)),type=np.recarray);recarray.view(recarray.dtype.fields或recarray.dtype,np.ndarray)”。
In [234]: list(zip(*arr.T))
Out[234]: [('Hello', '2.5', '3'), ('World', '3.6', '2')]
In [235]: np.array(_, dtype=dt)
Out[235]: 
array([(b'Hello',  2.5, 3), (b'World',  3.6, 2)], 
      dtype=[('Col1', 'S8'), ('Col2', '<f8'), ('Col3', '<i8')])
In [236]: np.rec.fromarrays(arr.T, dtype=dt)
Out[236]: 
rec.array([(b'Hello',  2.5, 3), (b'World',  3.6, 2)], 
          dtype=[('Col1', 'S8'), ('Col2', '<f8'), ('Col3', '<i8')])
In [237]: newarr = np.empty(arr.shape[0], dtype=dt)
In [238]: for n, v in zip(newarr.dtype.names, arr.T):
     ...:     newarr[n] = v
     ...:     
In [239]: newarr
Out[239]: 
array([(b'Hello',  2.5, 3), (b'World',  3.6, 2)], 
      dtype=[('Col1', 'S8'), ('Col2', '<f8'), ('Col3', '<i8')])
dtype = np.dtype([("Col1","S8"),("Col2","f8"),("Col3","i8")])
myarray = np.array([("Hello",2.5,3),("World",3.6,2)], dtype=dtype)
np.array(np.rec.fromarrays(myarray.transpose(), names=dtype.names).astype(dtype=dtype).tolist(), dtype=dtype)