如何缩短扁平化时间numpy.append文件

2024-09-26 22:55:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个从第三方类继承的数据结构,该类重载__getitem__,返回一个元组。你知道吗

现在,我在其他地方编写了代码,涉及将这些对象的集合附加到numy数组:

class ThirdPartyThing:

    def __init__(self, size):
        self.size = size

    def __len__(self):
        return self.size

    def __getitem__(self, key):
        return (self, key)

    def __iter__(self):
        return zip([self] * self.size, range(self.size))

class MyThing(ThirdPartyThing):
    pass

x = numpy.array([], dtype = MyThing, ndmin = 1)
temp = [MyThing(1) for _ in range(5)]
x = numpy.append(x, temp)

当我这样做的时候,我所期望的是一个Numpy数组,有五个类型为MyThing的对象,但是我得到的是一个一维数组,如下所示:

[MyThing(), 0, MyThing(), 0, MyThing(), 0, MyThing(), 0, MyThing(), 0]

它的长度是10,其中其他元素都是整数。你知道吗

根据the docsappend如果axis没有定义,那么append会尝试展平数组,但在我的例子中,定义axis并没有什么区别。有没有办法避免这个陷阱?你知道吗

更新 仔细检查之后,我发现基类重载了__len__。我想这就是问题的根源。你知道吗


Tags: 对象keyselfnumpysizelenreturndef
1条回答
网友
1楼 · 发布于 2024-09-26 22:55:24

你的文章的准确副本:

In [1]: class MyThing: 
   ...:     pass 
   ...:  
   ...: x = numpy.array([], dtype = MyThing, ndmin = 1) 
   ...: temp = [MyThing() for _ in range(5)] 
   ...: x = numpy.append(x, temp)                                               
In [2]: x                                                                       
Out[2]: 
array([<__main__.MyThing object at 0x7f21b45cd2e8>,
       <__main__.MyThing object at 0x7f21b45cd278>,
       <__main__.MyThing object at 0x7f21b45cd240>,
       <__main__.MyThing object at 0x7f21b45cd320>,
       <__main__.MyThing object at 0x7f21b45cd390>], dtype=object)

至于np.append,其代码是:

def append(arr, values, axis=None):
    arr = asanyarray(arr)
    if axis is None:
        if arr.ndim != 1:
            arr = arr.ravel()
        values = ravel(values)
        axis = arr.ndim-1
    return concatenate((arr, values), axis=axis)

所以对于一个轴,它就是concatenate。如果没有它,则确保两个参数都是1d

你的x是(0,)形状,你的temp是一个5元素列表,它的数组变成(5,)形状,结果是(5,)

In [14]: x=numpy.array([], dtype = MyThing, ndmin = 1)                          
In [15]: x.shape                                                                
Out[15]: (0,)
In [16]: np.array(temp).shape                                                   
Out[16]: (5,)
In [17]: np.concatenate((x,temp)).shape                                         
Out[17]: (5,)

我看不出有什么问题。np.append中的“扁平化”不会影响代码。但正如我所说,我不喜欢np.append。它混淆了太多的新用户,而且是不需要的。直接使用concatenate。你知道吗

还包括ThirdPartyThing类的代码,但不要使用它。你知道吗


MyThing一个报告:

In [21]: MyThing.__repr__= lambda self: "MYTHING" 

并定义不同的temp

In [28]: temp1 = np.array([(MyThing(),0) for _ in range(3)])

现在我们看到appendravels的效果:

In [30]: np.append(x,temp1)                                                     
Out[30]: array([MYTHING, 0, MYTHING, 0, MYTHING, 0], dtype=object)

(3,2)temp1在加入(0,)x之前变成(6m,)。你知道吗

添加axis=0不起作用,因为维数不同。你知道吗


使用您编辑的代码:

In [64]: temp = np.array([MyThing(1) for _ in range(3)])                        
In [65]: temp                                                                   
Out[65]: 
array([[[<__main__.MyThing object at 0x7f21adbc5048>, 0]],

       [[<__main__.MyThing object at 0x7f21adbc5a58>, 0]],

       [[<__main__.MyThing object at 0x7f21adbc5470>, 0]]], dtype=object)

In [66]: temp.shape                                                             
Out[66]: (3, 1, 2)

或者用我的报告:

In [67]: MyThing.__repr__= lambda self: "MYTHING"                               
In [68]: temp                                                                   
Out[68]: 
array([[[MYTHING, 0]],

       [[MYTHING, 0]],

       [[MYTHING, 0]]], dtype=object)

In [70]: np.append(x,temp)                                                      
Out[70]: array([MYTHING, 0, MYTHING, 0, MYTHING, 0], dtype=object)

加上axis=0仍然可以

ValueError: all the input arrays must have same number of dimensions

无论您如何构造它,尝试将(0,)形状数组与(3,1,2)形状数组连接需要进行一些调整。你知道吗

但是为什么要加入这两个数组呢?(0,)形状数组最初是从哪里来的?你知道吗


构建列表的方式是问题的根源:

In [87]: [MyThing(1) for _ in range(3)]                                         
Out[87]: [MYTHING, MYTHING, MYTHING]
In [88]: np.array(_)                                                            
Out[88]: 
array([[[MYTHING, 0]],

       [[MYTHING, 0]],

       [[MYTHING, 0]]], dtype=object)
In [89]: [MyThing(i) for i in range(3)]      # different MyThing parameter each time                                   
Out[89]: [MYTHING, MYTHING, MYTHING]
In [90]: np.array(_)                                                            
Out[90]: array([MYTHING, MYTHING, MYTHING], dtype=object)

但是np.array([MyThing(2),MyThing(3)])会导致某种无限循环。你知道吗


但是回到append的问题。通常,在迭代地构建数组时,我们建议在列表中收集值(list append非常快),并在末尾执行一个数组构造(使用np.arraynp.stack和/或np.concatenate)。你知道吗

不建议以迭代方式进行连接。它比较慢,并且在创建有效的起始“空”数组时出现问题。你的x看起来就像一个空的启动者。np.append给出了一种错误的感觉,即这种iteative数组构造与list-append方法一样好。不是。这就是我不喜欢np.append的部分原因。使用concatenate时,至少必须直接解决数组维度的差异。而且concatenate需要一个列表,而不仅仅是两个参数。所以它在循环之外工作。你知道吗


对于leniterThirdPartyThing(通过继承MyThing)是一个iterable。np.array从这些东西的列表构造数组时,也会尝试对它们进行迭代(与使用列表时相同)。你知道吗

我可以创建一个空的对象数组,并分别填充它,而不是从一个MyThing列表生成数组。现在我得到了这些对象的“干净”数组:

In [93]: temp = np.empty(5, object)                                             
In [94]: temp                                                                   
Out[94]: array([None, None, None, None, None], dtype=object)
In [95]: for i in range(3): 
    ...:     temp[i] = MyThing(1) 
    ...:                                                                        
In [96]: temp                                                                   
Out[96]: array([MYTHING, MYTHING, MYTHING, None, None], dtype=object)

甚至

In [100]: temp[:] = [MyThing(1) for _ in range(5)]                              
In [101]: temp                                                                  
Out[101]: array([MYTHING, MYTHING, MYTHING, MYTHING, MYTHING], dtype=object)

只是不要把清单给np.array!你知道吗

这种temp可以通过多种方式连接:

In [102]: np.concatenate([temp,temp,temp])                                      
Out[102]: 
array([MYTHING, MYTHING, MYTHING, MYTHING, MYTHING, MYTHING, MYTHING,
       MYTHING, MYTHING, MYTHING, MYTHING, MYTHING, MYTHING, MYTHING,
       MYTHING], dtype=object)
In [103]: np.vstack([temp,temp,temp])                                           
Out[103]: 
array([[MYTHING, MYTHING, MYTHING, MYTHING, MYTHING],
       [MYTHING, MYTHING, MYTHING, MYTHING, MYTHING],
       [MYTHING, MYTHING, MYTHING, MYTHING, MYTHING]], dtype=object)
In [105]: np.append(x,temp)                                                     
Out[105]: array([MYTHING, MYTHING, MYTHING, MYTHING, MYTHING], dtype=object)

相关问题 更多 >

    热门问题