添加不同形状的numpy数组

2021-03-02 15:26:12 发布

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

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

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

或者

^{pr2}$

我事先不知道形状。在

我在搞乱np形状对于每一个,试着找到包含它们的最小形状,将它们嵌入到该形状的零位数组中,然后将它们相加。但这似乎要做很多工作,有没有更简单的方法?在

提前谢谢!在

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

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)

不漂亮:-/

3条回答
网友
1楼 ·

这是我能想到的最好的:

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循环,例如:

^{pr2}$
网友
2楼 ·

I'm messing around with the output of np.shape for each, trying to find the smallest shape which holds both of them, embedding each in a zero-ed array of that shape and then adding them. But it seems rather a lot of work, is there an easier way?

得到np.shape很简单,找到包含这两个元素的最小形状非常容易,当然添加也很简单,所以唯一“大量工作”的部分就是“将每个元素嵌入到该形状的零位数组中”。在

是的,您可以通过调用^{}方法(或者^{}函数,如果您想复制而不是在原地更改它们),就可以消除这种情况。正如文件所解释的:

Enlarging an array: … missing entries are filled with zeros

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

>>> 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]])
网友
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)

相关问题