【问题标题】:adding numpy arrays of differing shapes添加不同形状的numpy数组
【发布时间】:2019-12-05 19:30:22
【问题描述】:

我想添加两个不同形状的 numpy 数组,但没有广播,而是将“缺失”值视为零。可能是最简单的例子,比如

[1, 2, 3] + [2] -> [3, 2, 3]

[1, 2, 3] + [[2], [1]] -> [[3, 2, 3], [1, 0, 0]]

我事先不知道形状。

我正在搞乱每个 np.shape 的输出,试图找到容纳它们的最小形状,将每个形状嵌入到该形状的零数组中,然后添加它们。但这似乎相当多的工作,有没有更简单的方法?

提前致谢!

编辑:我所说的“大量工作”是指“为我做很多工作”而不是为机器,我追求优雅而不是效率:我努力使它们保持最小的形状是

def pad(a, b) :
    sa, sb = map(np.shape, [a, b])
    N = np.max([len(sa),len(sb)])
    sap, sbp = map(lambda x : x + (1,)*(N-len(x)), [sa, sb])
    sp = np.amax( np.array([ tuple(sap), tuple(sbp) ]), 1)

不漂亮:-/

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    我正在搞乱每个 np.shape 的输出,试图找到容纳它们的最小形状,将每个形状嵌入到该形状的零数组中,然后添加它们。不过好像工作量比较大,有没有更简单的方法?

    获取np.shape 很简单,找到同时容纳两者的最小形状非常容易,当然添加也很简单,因此唯一的“大量工作”部分是“将每个形状嵌入到零数组中那种形状”。

    是的,您可以通过调用resize 方法(或resize 函数,如果您想制作副本而不是就地更改它们)来消除这种情况。正如文档解释的那样:

    扩大数组:……缺失的条目用零填充

    例如,如果您静态地知道维度:

    >>> a1 = np.array([[1, 2, 3], [4, 5, 6]])
    >>> a2 = np.array([[2], [2]])
    >>> shape = [max(a.shape[axis] for a in (a1, a2)) for axis in range(2)]
    >>> a1.resize(shape)
    >>> a2.resize(shape)
    >>> print(a1 + a2)
    array([[3, 4, 3],
           [4, 5, 6]])
    

    【讨论】:

    • 在这里调整大小不正确,试试a2.resize(4, 4)。如果输入有不同的暗淡,这也会失败。
    【解决方案2】:

    这是我能想到的最好的:

    import numpy as np
    
    def magic_add(*args):
        n = max(a.ndim for a in args)
        args = [a.reshape((n - a.ndim)*(1,) + a.shape) for a in args]
        shape = np.max([a.shape for a in args], 0)
        result = np.zeros(shape)
    
        for a in args:
            idx = tuple(slice(i) for i in a.shape)
            result[idx] += a
        return result
    

    如果你知道你期望结果有多少维度,你可以稍微清理一下 for 循环,比如:

    for a in args:
        i, j = a.shape
        result[:i, :j] += a
    

    【讨论】:

    • 谢谢Bi,这很漂亮
    【解决方案3】:

    您可以尝试我的解决方案 - 对于 1 维数组,您必须将数组扩展为 维度 2(如下例所示),然后将其传递给函数。

    import numpy as np
    import timeit
    
    
    matrix1 = np.array([[0,10],
                        [1,20],
                        [2,30]])
    matrix2 = np.array([[0,10],
                        [1,20],
                        [2,30],
                        [3,40]])
    matrix3 = np.arange(0,0,dtype=int) # empty numpy-array
    matrix3.shape = (0,2) # reshape to 0 rows
    matrix4 = np.array([[0,10,100,1000],
                        [1,20,200,2000]])
    matrix5 = np.arange(0,4000,1)
    matrix5 = np.reshape(matrix5,(4,1000))
    matrix6 = np.arange(0.0,4000,0.5)
    matrix6 = np.reshape(matrix6,(20,400))
    matrix1 = np.array([1,2,3])
    matrix1 = np.expand_dims(matrix1, axis=0)
    matrix2 = np.array([2,1])
    matrix2 = np.expand_dims(matrix2, axis=0)
    
    
    def add_2d_matrices(m1, m2, pos=(0,0), filler=None):
        """
        Add two 2d matrices of different sizes or shapes,
        offset by xy coordinates, whereat x is "from left to right" (=axis:1)
        and y is "from top to bottom" (=axis:0)
        Parameterse:
            - m1: first matrix
            - m2: second matrix
            - pos: tuple (x,y) containing coordinates for m2 offset,
            - filler: gaps are filled with the value of filler (or zeros)
        Returns:
            - 2d array (float):
                containing filler-values, m1-values, m2-values
                or the sum of m1,m2 (at overlapping areas)
        Author:
            Reinhard Daemon, Austria
        """
        # determine shape of final array:
        _m1 = np.copy(m1)
        _m2 = np.copy(m2)
        x,y = pos
        y1,x1 = _m1.shape
        y2,x2 = _m2.shape
        xmax = max(x1, x2+x)
        ymax = max(y1, y2+y)
    
        # fill-up _m1 array with zeros:
        y1,x1 = _m1.shape
        diff = xmax - x1
        _z = np.zeros((y1,diff))
        _m1 = np.hstack((_m1,_z))
        y1,x1 = _m1.shape
        diff = ymax - y1
        _z = np.zeros((diff,x1))
        _m1 = np.vstack((_m1,_z))
    
        # shift _m2 array by 'pos' and fill-up with zeros:
        y2,x2 = _m2.shape
        _z = np.zeros((y2,x))
        _m2 = np.hstack((_z,_m2))
        y2,x2 = _m2.shape
        diff = xmax - x2
        _z = np.zeros((y2,diff))
        _m2 = np.hstack((_m2,_z))
        y2,x2 = _m2.shape
        _z = np.zeros((y,x2))
        _m2 = np.vstack((_z,_m2))
        y2,x2 = _m2.shape
        diff = ymax - y2
        _z = np.zeros((diff,x2))
        _m2 = np.vstack((_m2,_z))
    
        # add the 2 arrays:
        _m3 = _m1 + _m2
    
        # find and fill the "unused" positions within the summed array:
        if filler not in (None,0,0.0):
            y1,x1 = m1.shape
            y2,x2 = m2.shape
            x1min = 0
            x1max = x1-1
            y1min = 0
            y1max = y1-1
            x2min = x
            x2max = x + x2-1
            y2min = y
            y2max = y + y2-1
            for xx in range(xmax):
                for yy in range(ymax):
                    if x1min <= xx <= x1max and y1min <= yy <= y1max:
                        continue
                    if x2min <= xx <= x2max and y2min <= yy <= y2max:
                        continue
                    _m3[yy,xx] = filler
    
        return(_m3)
    
    
    
    
    
    
    t1 = timeit.Timer("add_2d_matrices(matrix5, matrix6, pos=(1,1), filler=111.111)", \
    "from __main__ import add_2d_matrices,matrix5,matrix6")
    print("ran:",t1.timeit(number=10), "milliseconds")
    
    print("\n\n")
    my_res = add_2d_matrices(matrix1, matrix2, pos=(1,1), filler=99.99)
    print(my_res)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-22
      • 2016-11-20
      • 2018-12-23
      • 1970-01-01
      • 2016-02-14
      相关资源
      最近更新 更多