2013-09-23 154 views
3

我尝试通过为每列指定名称来将10x2数组转换为记录。将numpy数组转换为numpy记录数组

我尝试这样:

t = arange (10) 
>>> n = dstack([t, 
       roll (t, 1), 
       roll (t, -1)])[0] 
... ... >>> 
>>> n = n[:,1:3] 
>>> n 
array([[9, 1], 
     [0, 2], 
     [1, 3], 
     [2, 4], 
     [3, 5], 
     [4, 6], 
     [5, 7], 
     [6, 8], 
     [7, 9], 
     [8, 0]]) 
>>> nt = [('left', int), ('right', int)] 
>>> array (n, nt) 
array([[(9, 9), (1, 1)], 
     [(0, 0), (2, 2)], 
     [(1, 1), (3, 3)], 
     [(2, 2), (4, 4)], 
     [(3, 3), (5, 5)], 
     [(4, 4), (6, 6)], 
     [(5, 5), (7, 7)], 
     [(6, 6), (8, 8)], 
     [(7, 7), (9, 9)], 
     [(8, 8), (0, 0)]], 
     dtype=[('left', '<i8'), ('right', '<i8')]) 
>>> 

要我surprize,每一行的元素是元组,而不是int类型的数字。

我该如何纠正这一点,并使n的每一行看起来像[ 9,1 ]而不是[(9, 9), (1, 1)]

+1

可能重复一个结构化数组](http://stackoverflow.com/questions/3622850/converting-a-2d-numpy-array-to-a-structured-array) – askewchan

+0

我读过这篇文章,尽管我努力去理解它并将其转换如我所愿,我无法在那里找到答案。另一方面,迄今为止收到的答案是有效的。 – alinsoar

+0

是的,从现有数组中重构数据的构造有点奇怪,因为您将过去单独的元素放入一个元素元组中。 – askewchan

回答

2

有希望在纯numpy的一种更好的方式,而是让你开始:

>>> nt = [('left', int), ('right', int)] 
>>> n 
array([[9, 1], 
     [0, 2], 
     [1, 3], 
     [2, 4], 
     [3, 5], 
     [4, 6], 
     [5, 7], 
     [6, 8], 
     [7, 9], 
     [8, 0]]) 

>>> out = np.array(np.zeros(n.shape[0]),nt) 
>>> out 
array([(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), 
     (0, 0), (0, 0)], 
     dtype=[('left', '<i8'), ('right', '<i8')]) 

>>> out['left']=n[:,0] 
>>> out['right']=n[:,1] 

>>> out 
array([(9, 1), (0, 2), (1, 3), (2, 4), (3, 5), (4, 6), (5, 7), (6, 8), 
     (7, 9), (8, 0)], 
     dtype=[('left', '<i8'), ('right', '<i8')]) 

>>> out['left'] 
array([9, 0, 1, 2, 3, 4, 5, 6, 7, 8]) 

当然有大熊猫答案:

>>> import pandas as pd 
>>> df = pd.DataFrame(n,columns=['left','right']) 
>>> df 
    left right 
0  9  1 
1  0  2 
2  1  3 
3  2  4 
4  3  5 
5  4  6 
6  5  7 
7  6  8 
8  7  9 
9  8  0 

一件好事约大熊猫dataframes:

>>> df.values 
array([[9, 1], 
     [0, 2], 
     [1, 3], 
     [2, 4], 
     [3, 5], 
     [4, 6], 
     [5, 7], 
     [6, 8], 
     [7, 9], 
     [8, 0]]) 
+0

这很好。 – alinsoar

3

您可以使用新的dtype创建视图,并且它看起来是相同的数据:

In [150]: nt = [('left',np.int),('right',np.int)] 

In [151]: n 
Out[151]: 
array([[9, 1], 
     [0, 2], 
     [1, 3], 
     [2, 4], 
     [3, 5], 
     [4, 6], 
     [5, 7], 
     [6, 8], 
     [7, 9], 
     [8, 0]]) 

In [152]: n.view(nt) 
Out[152]: 
array([[(9, 1)], 
     [(0, 2)], 
     [(1, 3)], 
     [(2, 4)], 
     [(3, 5)], 
     [(4, 6)], 
     [(5, 7)], 
     [(6, 8)], 
     [(7, 9)], 
     [(8, 0)]], 
     dtype=[('left', '<i8'), ('right', '<i8')]) 

这保持了2D图形,虽然:

In [160]: n_struct = n.view(nt) 

In [161]: n_struct.shape 
Out[161]: (10, 1) 

In [162]: n_struct = n.view(nt).reshape(n.shape[0]) 

In [163]: n_struct 
Out[163]: 
array([(9, 1), (0, 2), (1, 3), (2, 4), (3, 5), (4, 6), (5, 7), (6, 8), 
     (7, 9), (8, 0)], 
     dtype=[('left', '<i8'), ('right', '<i8')]) 

至于你问,访问是这样的:

In [170]: n_struct['left'] 
Out[170]: array([9, 0, 1, 2, 3, 4, 5, 6, 7, 8]) 

In [171]: n_struct['right'] 
Out[171]: array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) 

警告,从@Ophion,是这仅在dtypes兼容时才有效,因为ndarray.view(dtype)将原始数据解释为它是给定的dtype,它不会转换将数据添加到新给定的dtype。换句话说,(从文件),

a.view(some_dtype) constructs a view of the array's memory with a different data-type. This can cause a reinterpretation of the bytes of memory.

+0

似乎很有趣,但现在这个数组是元组。我需要经常执行此操作,而且我需要非常快的操作。另一方面,如何'左'从元组数组中提取第一个元素? – alinsoar

+1

这就是'record'数组:一个元组数组(因为你的'dtype'是一个包含两个'int'的元组)。 – askewchan

+0

您可以定义其他类型,例如只用1个操作直接获得名称列吗? – alinsoar

1

如果底层dtypes是不兼容,view方法是行不通的。 fallback选项是与元组的列表来填充记录阵列:

In [128]: x=np.arange(12).reshape(4,3) 

In [129]: y=np.zeros((4,),dtype=[('x','f'),('y','f'),('z','f')]) 

In [130]: y 
Out[130]: 
array([(0.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, 0.0)], 
     dtype=[('x', '<f4'), ('y', '<f4'), ('z', '<f4')]) 

In [131]: y[:]=[tuple(row) for row in x] 

In [132]: y 
Out[132]: 
array([(0.0, 1.0, 2.0), (3.0, 4.0, 5.0), (6.0, 7.0, 8.0), (9.0, 10.0, 11.0)], 
     dtype=[('x', '<f4'), ('y', '<f4'), ('z', '<f4')]) 

元组的该列表可以在初始构造中使用:的[将2D numpy的阵列

In [135]: np.array([tuple(row) for row in x],y.dtype) 
Out[135]: 
array([(0.0, 1.0, 2.0), (3.0, 4.0, 5.0), (6.0, 7.0, 8.0), (9.0, 10.0, 11.0)], 
     dtype=[('x', '<f4'), ('y', '<f4'), ('z', '<f4')])