代码之家  ›  专栏  ›  技术社区  ›  user3357979

查找阵列的二维切片的交点

  •  2
  • user3357979  · 技术社区  · 9 年前

    我想得到一排排 B 哪里:

    1. 如果 A[:,0] 等于 B[:,0] B[:,2] 然后 A[:,1] 必须等于 B[:,1] B[:,3] 分别地
    2. A[:,0] 不等于 B[i,0] B[i,2]

    例如:

    A=np.array([[101,  1],
                [103,  3]])
    
    B=np.array([[100,1,101,1],
                [100,1,102,1],
                [100,1,103,3],
                [100,2,101,2],
                [100,2,103,2],
                [101,1,100,3],
                [101,1,103,2],
                [101,4,100,4],
                [101,4,103,4],
                [104,5,102,3]])
    
    R=np.array([[100,1,101,1],
                [100,1,102,1],
                [100,1,103,3],
                [101,1,100,3],
                [104,5,102,3]])
    

    我从这里尝试了解决方案( Implementation of numpy in1d for 2D arrays? )但我收到一个错误,因为我无法使用 view 使用数组的切片。

    谢谢你的帮助!

    2 回复  |  直到 7 年前
        1
  •  3
  •   askewchan bogatron    9 年前

    我会先简化你的规则。暂时忽略形状,让我们考虑 A B 是成对的列表。那么您的要求是,如果一对中的左搭档与 A. ,则正确的合作伙伴也必须匹配。

    这是 material implication ,写为 left match → right match 好的部分是

    (x → y) 只有在以下情况下才是正确的 either (x is false) or (y is true)

    后者很容易编码。对于您 left match x = A[..., 0] == B[..., 0] 以及 right match y = A[..., 1] == B[..., 1] 。所以检查一下 x → y ,你只要检查一下 not(x) or y ,可以写成 ~x | y .

    要处理形状,请使用整形,以便 left right 仅沿一个轴(最后一个轴),然后广播以检查其中任一对是否匹配 A. ,然后检查每行中的所有对是否满足条件 B 。所有这些看起来都是这样的(请参见下面的详细说明):

    def implicate(A, B):
        # axes: (i, apair, bpair, partner)
        a = A[None, :, None, :]
        b = B.reshape(-1, 1, 2, 2)
        m = a == b
        m = ~m[...,0] | m[...,1] # require the implication rule along last axis
        m = m.all((1,2))         # both pairs in each A and B must comply (axes 1,2)
        return m, B[m]           # probably want to return only one of these
    

    以下是它如何应用于您的系统。

    1. 要绕过这些形状,只需巧妙地使用广播,然后检查行中的所有对是否都符合上述要求。

      a = A[None, :, None, :] # or A.reshape(1, A.shape[0], 1, A.shape[1]) to add two broadcasting axes
      b = B.reshape(-1, 1, 2, 2) # this is B.reshape(10, 1, 2, 2) without needing to know 10
      

      这为每个 a b 四个维度: (i, a_pair, b_pair, partner) 也就是说,沿第一个轴进行切片 i (中的行 B ),第二个选择 A. ,第三个这样做 B ,最后一个选择每对中两个伙伴中的哪一个。要概括这一点(如果您事先不知道两者的形状),可以使用:

      a = A[None, :, None, :] # or A.reshape(1, -1, 1, 2)
      b = B.reshape(len(B), 1, -1, 2)
      

      其中 -1 s将允许任意数量的对 A. B 这个 2 我们假设我们正在讨论配对。

    2. 现在,我们只需获得一个匹配数组:

      m = a == b
      

      它有形状 (10, 2, 2, 2) ,再次代表 (i,a对,b对,合伙人) .

    3. 接下来,我们应用上述材料含义的要求。为了更容易阅读,我们首先将所有的左伙伴与右伙伴分开,然后检查条件是否成立。这里有

      left  = m[...,0]
      right = m[...,1]
      m = ~left | right
      

      这消除了最后一个轴 partner ,正在离开 (i, b_pair) .

    4. 最后,我们希望确保该规则适用于 B ,由 b_pair 轴(2)。

      m = m.all(2)
      

      当然,它必须符合 A. ( a_pair 轴为1):

      m = m.all(1)
      

    将所有内容放在一起,并将 any 在最后一步调用时,您将得到上面的函数。

        2
  •  0
  •   Divakar    9 年前

    如果我正确理解了问题,你可以使用 np.in1d -

    # Mask for A[:,0] is equal to either B[:,0] or B[:,2]
    mask1 = (np.in1d(B[:,::2],A[:,0]).reshape(-1,2)).any(1)
    
    # Mask for A[:,1] has to be equal to B[:,1] or B[:,3]
    mask2 = (np.in1d(B[:,1::2],A[:,1]).reshape(-1,2)).any(1)
    
    # Mask for A[:,0] is not equal to either B[i,0] and B[i,2]
    mask3 = ~(np.in1d(B[:,::2],A[:,0]).reshape(-1,2)).any(1)
    
    # Finally combine all masks as per requirements
    out = B[(mask1 & mask2) | mask3]
    

    样品运行-

    In [361]: A
    Out[361]: 
    array([[101,   1],
           [103,   3]])
    
    In [362]: B
    Out[362]: 
    array([[100,   1, 101,   1],
           [100,   1, 102,   1],
           [100,   1, 103,   3],
           [100,   2, 101,   2],
           [100,   2, 103,   2],
           [101,   1, 100,   3],
           [101,   1, 103,   2],
           [101,   4, 100,   4],
           [101,   4, 103,   4],
           [104,   5, 102,   3]])
    
    In [363]: out
    Out[363]: 
    array([[100,   1, 101,   1],
           [100,   1, 102,   1],
           [100,   1, 103,   3],
           [101,   1, 100,   3],
           [101,   1, 103,   2],
           [104,   5, 102,   3]])