Numpy:创建浅层复制的Python对象数组

时间:2015-08-06 01:23:13

标签: python arrays numpy

我有一个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

但这似乎不太优雅。有没有人有更好的解决方案?

1 个答案:

答案 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)

在其中任何一个中,元素都可以在创建后用你的点替换。