Python 测试数组是否可以广播到形状?

Python 测试数组是否可以广播到形状?,python,arrays,numpy,multidimensional-array,Python,Arrays,Numpy,Multidimensional Array,测试阵列是否可以广播到给定形状的最佳方法是什么 trying的“pythonic”方法不适用于我的案例,因为其目的是对操作进行惰性评估 我在问如何实现下面的is\u broadcastable: >>> x = np.ones([2,2,2]) >>> y = np.ones([2,2]) >>> is_broadcastable(x,y) True >>> y = np.ones([2,3]) >>> i

测试阵列是否可以广播到给定形状的最佳方法是什么

try
ing的“pythonic”方法不适用于我的案例,因为其目的是对操作进行惰性评估

我在问如何实现下面的
is\u broadcastable

>>> x = np.ones([2,2,2])
>>> y = np.ones([2,2])
>>> is_broadcastable(x,y)
True
>>> y = np.ones([2,3])
>>> is_broadcastable(x,y)
False
或者更好:

>>> is_broadcastable(x.shape, y.shape)
你可以用。例如:

In [47]: x = np.ones([2,2,2])

In [48]: y = np.ones([2,3])

In [49]: try:
   ....:     b = np.broadcast(x, y)
   ....:     print "Result has shape", b.shape
   ....: except ValueError:
   ....:     print "Not compatible for broadcasting"
   ....:     
Not compatible for broadcasting

In [50]: y = np.ones([2,2])

In [51]: try:
   ....:     b = np.broadcast(x, y)
   ....:     print "Result has shape", b.shape
   ....: except ValueError:
   ....:     print "Not compatible for broadcasting"
   ....:
Result has shape (2, 2, 2)

对于延迟求值的实现,您可能也会发现它很有用。

如果您只是想避免用给定的形状具体化数组,您可以使用:

import numpy as np
from numpy.lib.stride_tricks import as_strided

def is_broadcastable(shp1, shp2):
    x = np.array([1])
    a = as_strided(x, shape=shp1, strides=[0] * len(shp1))
    b = as_strided(x, shape=shp2, strides=[0] * len(shp2))
    try:
        c = np.broadcast_arrays(a, b)
        return True
    except ValueError:
        return False

is_broadcastable((1000, 1000, 1000), (1000, 1, 1000))  # True
is_broadcastable((1000, 1000, 1000), (3,))  # False

这是内存效率很高的,因为a和b都由一条记录支持

我真的认为你们考虑得太多了,为什么不简单一点呢

def is_broadcastable(shp1, shp2):
    for a, b in zip(shp1[::-1], shp2[::-1]):
        if a == 1 or b == 1 or a == b:
            pass
        else:
            return False
    return True

要将其推广到任意多个形状,可以按如下方式执行:

def is_broadcast_compatible(*shapes):
    if len(shapes) < 2:
        return True
    else:
        for dim in zip(*[shape[::-1] for shape in shapes]):
            if len(set(dim).union({1})) <= 2:
                pass
            else:
                return False
        return True
import unittest


class TestBroadcastCompatibility(unittest.TestCase):
    def check_true(self, *shapes):
        self.assertTrue(is_broadcast_compatible(*shapes), msg=shapes)

    def check_false(self, *shapes):
        self.assertFalse(is_broadcast_compatible(*shapes), msg=shapes)

    def test(self):
        self.check_true((1, 2, 3), (1, 2, 3))
        self.check_true((3, 1, 3), (3, 3, 3))
        self.check_true((1,), (2,), (2,))

        self.check_false((1, 2, 3), (1, 2, 2))
        self.check_false((1, 2, 3), (1, 2, 3, 4))
        self.check_false((1,), (2,), (3,))

对于要检查任意数量的类似数组的对象(与传递形状相反)的情况,我们可以利用
np.nditer
进行检查


请注意,这仅适用于
np.ndarray
或定义
\uuuu数组\uuuu
的类(将被调用)

numpy.broadcast\u shapes
从numpy 1.20开始就可以使用,因此它可以很容易地实现:

将numpy导入为np
def可广播(shp1、shp2):
尝试:
c=np.广播形状(shp1、shp2)
返回真值
除值错误外:
返回错误
在引擎盖下,它使用零长度列表numpy数组调用
广播_数组
,方法如下:

np.empty(shp, dtype=[])

这样可以避免分配内存。它类似于由提出的解决方案,但不依赖于
as_strip
技巧,我发现这有点令人困惑。

参考:
广播_数组
是我为了获得惰性而寻找的,但我仍然需要一个验证阶段-如何测试形状a是否可以广播到形状B,假设我手头没有形状B的数组?我想不出这有什么错。。。我可能没有遗漏任何微妙的额外规则,是吗?
np.empty(shp, dtype=[])