从namedtuple列表中编写numpy.array()

时间:2018-12-01 23:59:58

标签: python arrays numpy namedtuple

我有一个namedtuple列表,我想将其写入numpy数组。 元组具有属性“颜色”(一组两种颜色)和“数字”(整数),格式为:

from collections import namedtuple
import numpy as np

NamedTuple = namedtuple('tuple',['colors','number'])

L = [NamedTuple({'violet', 'blue'}, 4),  
    NamedTuple({'orange', 'blue'}, 1),  
    NamedTuple({'green', 'blue'}, 3),  
    NamedTuple({'orange', 'red'}, 2)]
L
>>>[tuple(colors={'blue', 'violet'}, number=4)...]
L[3].colors
>>>{'orange', 'red'}

我想从L中编写一个2x2数组,例如:

Array[1][1].colors
>>>{'orange', 'red'}

Array = numpy.array(L)
>>>[[{'blue', 'violet'} 4]
   [{'blue', 'orange'} 1]
   [{'blue', 'green'} 3]
   [{'red', 'orange'} 2]

给我一​​个元组数组,而不是namedtuple,它们具有'no attribute'colors'
更糟糕的是,如果我尝试将Array整形为2x2,我发现我的namedtuple的每个属性都被写为数组中的不同对象。

numpy.reshape(Array,(2,2))
>>>...error...
>>>'ValueError: cannot reshape array of size 8 into shape (2,2)'

我会以为上面的数组是4号?

如何在不更改namedtuple的情况下获取namedtuple数组,以便可以从数组的每个元素中调用不同的属性?

我想使用namedtuples作为数据结构的原因是,这样可以轻松且易读地调用每个对象的.color或.number属性。
我之所以要使用numpy数组而不是标准的嵌套列表,是因为此数组将成为整个项目中的动态对象,并且经常会对其进行搜索和更改,而且我知道python的标准列表对于这些对象的可怜性东西。
就上下文而言,我最终试图构建一个程序来玩我自己发明的纸牌游戏。 namedtuple用颜色和数字表示卡。数组代表牌桌,玩家可以随意更改和移动。这些命名元组将被大量改组,我不想担心它们的数据结构被更改。

1 个答案:

答案 0 :(得分:1)

因为NamedTupletuple的子类,所以根据L构造对象数组会导致(n,2)数组,就像我们将其作为元组列表或列表清单:

In [4]: np.array(L, object)
Out[4]: 
array([[{'violet', 'blue'}, 4],
       [{'blue', 'orange'}, 1],
       [{'blue', 'green'}, 3],
       [{'red', 'orange'}, 2]], dtype=object)
In [5]: _.shape
Out[5]: (4, 2)

这是一个窍门-首先向列表中添加一个None对象:

In [13]: arr = np.array(L+[None], object)[:-1]
In [14]: arr
Out[14]: 
array([tuple(colors={'violet', 'blue'}, number=4),
       tuple(colors={'blue', 'orange'}, number=1),
       tuple(colors={'blue', 'green'}, number=3),
       tuple(colors={'red', 'orange'}, number=2)], dtype=object)
In [15]: arr.shape
Out[15]: (4,)
In [16]: arr = np.reshape(arr,(2,2))
In [17]: arr
Out[17]: 
array([[tuple(colors={'violet', 'blue'}, number=4),
        tuple(colors={'blue', 'orange'}, number=1)],
       [tuple(colors={'blue', 'green'}, number=3),
        tuple(colors={'red', 'orange'}, number=2)]], dtype=object)

在先前的问题中,我发现frompyfunc是访问此类数组元素的最便捷工具(也是最快的工具)。

Most efficient way to set attributes on objects in array

In [18]: np.frompyfunc(lambda x: x.colors, 1,1)(arr)
Out[18]: 
array([[{'violet', 'blue'}, {'blue', 'orange'}],
       [{'blue', 'green'}, {'red', 'orange'}]], dtype=object)

要构建结构化数组,我们可以这样做:

In [19]: arr1 = np.array(L, dtype=[('colors', object), ('number', int)])
In [20]: arr1
Out[20]: 
array([({'violet', 'blue'}, 4), ({'blue', 'orange'}, 1),
       ({'blue', 'green'}, 3), ({'red', 'orange'}, 2)],
      dtype=[('colors', 'O'), ('number', '<i8')])

NamedTupletuple的子类,因此它可用作数据输入(例如元组列表)。

In [22]: arr1['colors']
Out[22]: 
array([{'violet', 'blue'}, {'blue', 'orange'}, {'blue', 'green'},
       {'red', 'orange'}], dtype=object)
In [23]: arr1['number']
Out[23]: array([4, 1, 3, 2])

初始化一维数组并分配元素的工作原理是

In [30]: arr2 = np.empty(4, object)
In [31]: arr2[:] = L
In [32]: arr2
Out[32]: 
array([tuple(colors={'violet', 'blue'}, number=4),
       tuple(colors={'blue', 'orange'}, number=1),
       tuple(colors={'blue', 'green'}, number=3),
       tuple(colors={'red', 'orange'}, number=2)], dtype=object)

填写np.empty((2,2), object)会比较棘手。


我可以使用以下方法从结构化数组的字段(或任何其他输入对列表)构造对象数组:

In [44]: np.frompyfunc(NamedTuple, 2,1)(arr1['colors'], arr1['number'])
Out[44]: 
array([tuple(colors={'violet', 'blue'}, number=4),
       tuple(colors={'blue', 'orange'}, number=1),
       tuple(colors={'blue', 'green'}, number=3),
       tuple(colors={'red', 'orange'}, number=2)], dtype=object)