我有一个namedtuple
对象列表,我想将它放入numpy
数组中,以便我可以使用方便的索引赋值操作。考虑像这样的输入,
In [3]: Point = namedtuple("Point", ["x", "y"])
In [4]: x_lst = [Point(1, 2), Point(3, 4)]
默认情况下,numpy将从其输入中创建2D数组
In [5]: numpy.array(x_lst)
Out[5]:
array([[1, 2],
[3, 4]])
In [6]: numpy.array(x_lst).shape
Out[6]: (2, 2)
可以在记录类型的范围内对此进行抑制,但它仍在对其输入进行某种类型操作(在这种情况下将每个元素转换为常规元组),
In [7]: numpy.core.records.array(x_lst)
Out[7]:
rec.array([(1, 2), (3, 4)],
dtype=[('f0', '<i8'), ('f1', '<i8')])
我设法解决了这个问题,
In [8]: result = numpy.full((2,), None, dtype=object)
In [9]: result[:] = x_lst
In [10]: type(result[0])
Out[10]: __main__.Point
但这似乎不太优雅。有没有人有更好的解决方案?
答案 0 :(得分:1)
我会用
In [1152]: xx=np.empty((2,),dtype=object)
In [1153]: xx[:] = x_lst
In [1154]: xx
Out[1154]: array([Point(x=1, y=2), Point(x=3, y=4)], dtype=object)
但是,是的,它与您的解决方案基本相同。
我在其他SO问题中观察到创建对象数组通常需要一些技巧。默认情况下,np.array()
会尝试从数据中创建最高维数字数组。您的namedtuple对象是可迭代的(它的一个特性),[i for i in Point(1,2)]
,因此np.array
x_lst
看起来就像一个元组列表:[(1,2),(3,4)]
。< / p>
创建一个空对象数组,并用[:]
填充它似乎是最简单的解决方案。
由于这些点是可迭代的,因此该阵列上的各种操作可能是不可预测的。例如:
In [1198]: xx.sum()
Out[1198]: (1, 2, 3, 4)
如果类不可迭代,则创建对象数组更简单:
In [1179]: class MyObject(object):
def __init__(self, *args):
self.args=args
......:
In [1180]: yy=np.array([MyObject(1,2),MyObject(1,2,3)])
In [1181]: yy
Out[1181]:
array([<__main__.MyObject object at 0xb18e0a8c>,
<__main__.MyObject object at 0xb18e0aac>], dtype=object)
In [1182]: yy[0].args
Out[1182]: (1, 2)
对于不同大小的列表或元组也是如此,它不能强制进入二维数组:
In [1183]: np.array([(1,2),(1,2,3)])
Out[1183]: array([(1, 2), (1, 2, 3)], dtype=object)
在其中任何一个中,元素都可以在创建后用你的点替换。