【问题标题】:Automatically truncate numpy arrays自动截断 numpy 数组
【发布时间】:2016-01-03 20:23:42
【问题描述】:

做的时候:

import numpy as np
a = np.array([1,2,3])
b = np.array([4,5,6,7])
print a+b

当然有错误:

ValueError: 操作数无法与形状 (3,) (4,) 一起广播

当两个不同大小的数组相加或相乘时,是否可以让 numpy 数组自动截断为最小大小?

示例:这里 a 的长度为 3,b 的长度为 4,所以我们在进行加法之前自动将 b 截断为长度 3。 a+b 的期望结果:

[5 7 9]

这可以通过子类化np.array来完成吗?

备注:我想避免必须自己手动使用a[:3] + b[:3] 截断所有数组。我希望能够只写a+b

【问题讨论】:

  • 数组总是一维的吗?

标签: python arrays numpy


【解决方案1】:

所以,首先:你想做的是坏的形式。重新定义简单的操作通常会引起各种头痛。为这样的事情子类化 np.array 似乎是一个可怕的想法。

话虽如此,还是可以做到的。这是一种天真的方法:

import numpy as np

class truncarray(np.ndarray):
    def __new__( cls, array ):
        obj = np.asarray(array).view(cls)
        return obj
    def __add__( a, b ):
        s = slice(0, min(len(a),len(b)))
        return np.add(a[s],b[s])
    __radd__ = __add__

a = truncarray([1,2,3])
b = truncarray([4,5,6,7])
a_array = np.array([1,2,3])
b_array = np.array([4,5,6,7])

现在,让我们看看这把一切搞砸了多少:

根据需要添加截断:

In [17]: a+b
Out[17]: truncarray([5, 7, 9])

添加数字不再有效:

In [18]: a_array+1
Out[18]: array([2, 3, 4])

In [19]: a+1
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-19-fdcaab9110f2> in <module>()
----> 1 a+1

<ipython-input-2-3651dc87cb0e> in __add__(a, b)
      4                 return obj
      5         def __add__( a, b ):
----> 6                 s = slice(0, min(len(a),len(b)))
      7                 return np.add(a[s],b[s])
      8         __radd__ = __add__

TypeError: object of type 'int' has no len()

当考虑 truncarrays 和数组的混合时,加法不再是传递的:

In [20]: a+b_array+a_array
Out[20]: truncarray([ 6,  9, 12])

In [21]: b_array+a+a_array
Out[21]: truncarray([ 6,  9, 12])

In [22]: b_array+a_array+a
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-22-bcd145daa775> in <module>()
----> 1 b_array+a_array+a

ValueError: operands could not be broadcast together with shapes (4,) (3,)

事实上,它甚至不是关联的(!):

In [23]: a+(b_array+a_array)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-23-413ce83f55c2> in <module>()
----> 1 a+(b_array+a_array)

ValueError: operands could not be broadcast together with shapes (4,) (3,)

至少,如果你这样做,你会想要为不同的类型添加处理。但请考虑 Anton 的回答:这是更安全的方法。

【讨论】:

    【解决方案2】:

    您可以将两个数组分割成较小的数组,然后将它们相加:

    min_size = min(a.size, b.size)
    c = a[:min_size] + b[:min_size]
    print(c)
    array([5, 7, 9])
    

    编辑

    如果您不想手动操作,可以编写一个函数:

    def add_func(*args):
        to_trunc = min(map(len, args))
        return np.sum([arg[:to_trunc] for arg in args], axis=0)
    
    print(add_func(a,b))
    [5 7 9]
    

    【讨论】:

    • 当然,这行得通,但是(我应该在问题中提到这一点)我想这样做而不必不必手动截断所有数组。 (在我的代码中,我有很多数组,我想避免像你建议的那样手动截断)
    • 抱歉,但我想要重新定义 + 运算符,使其自动截断并允许使用a+b。 (因此可能需要子类化np.array
    猜你喜欢
    • 2018-11-27
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多