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

Python 查找阵列的二维切片的交点,python,arrays,numpy,intersection,Python,Arrays,Numpy,Intersection,我想获得B的行,其中: 如果A[:,0]等于B[:,0]或B[:,2],则A[:,1]必须分别等于B[:,1]或B[:,3] 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],

我想获得
B
的行,其中:

  • 如果
    A[:,0]
    等于
    B[:,0]
    B[:,2]
    ,则
    A[:,1]
    必须分别等于
    B[:,1]
    B[:,3]
  • 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]])
    
    我从这里()尝试了解决方案,但出现了一个错误,因为我无法将
    view
    用于数组的切片


    谢谢你的帮助

    如果我理解正确,你可以使用-

    样本运行-

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

    我会先简化你的规则。现在忽略这些形状,让我们考虑<代码> A < /COD>和<代码> B >代码>是对的列表。那么您的要求是,如果一对中的左搭档与
    a
    中的左搭档之一匹配,则右搭档也必须匹配

    这是的定义,写为左匹配→ 右匹配。好在

    (x)→ y) 
    仅在
    为(x为假)或(y为真)

    后者很容易编码。对于您来说,
    左匹配是
    x=A[…,0]==B[…,0]
    右匹配是
    y=A[…,1]==B[…,1]
    。所以要检查
    x→ y
    ,您只需选中
    而不是(x)或y
    ,它们可以写成
    ~x | y

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


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

  • 要绕过这些形状,只需很好地使用广播,然后检查上述内容是否适用于行中的所有对

    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\u对,b\u对,伙伴)
    ,也就是说,你在第一个轴上切片,沿着
    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
    s假设我们正在讨论配对

  • 现在,我们可以通过以下方式获得匹配数组:

    m = a == b
    
    它的形状是
    (10,2,2,2)
    ,同样代表
    (i,a,b,partner)

  • 接下来,我们应用对实质含义的要求,如上所述。为了便于阅读,我们首先将所有左伙伴与右伙伴分开,然后检查条件是否保持。我们有

    left  = m[...,0]
    right = m[...,1]
    m = ~left | right
    
    这消除了最后一个轴
    伙伴
    ,留下
    (i,b_对)

  • 最后,我们希望确保该规则适用于
    B
    的每一行中的所有对,这是由
    B_对
    轴(2)给出的

    当然,它必须符合
    A
    中所有对的匹配(
    A\u对
    轴为1):


  • 把它们放在一起,并结合最后一步中的
    任何
    调用,就得到了上面的函数。

    我认为这与OP中的预期结果不匹配。@askewchan是的,我认为预期输出有错误。我在评论中发布了一些让我感到困惑的东西。那么,从
    B
    中选择行时,
    case1
    case2
    是否都必须为真。另外,在
    案例1
    中,
    “then”
    是否意味着
    “A[:,0]等于B[:,0]或B[:,2]”
    “[:,1]必须等于B[:,1]或B[:,3]”
    从B中选择行时必须再次为真?@Divakar,案例
    1
    是一个条件语句,而case
    2
    只是一个语句。只要case
    2
    为真,case
    1
    则无效(如果
    1
    中的
    if
    为假,则支持该条件)。案例
    1
    的前半部分并不是选择的过滤器(不管
    a[:,0]
    是否匹配
    B[:,偶数]
    中的一个,只要存在匹配,然后
    a[:,1]
    匹配相应的
    B[:,奇数]
    。因此,逻辑上可以忽略大小写
    2
    ,得到相同的行。也许@user3357979可以确认吗?@askewchan就是这样correct@user3357979,收到您的评论并注意到我的代码中有错误;它适用于您的示例,但有一个极端情况,即它错过了两对
    a
    中的匹配可以交叉的位置。请看我的最新答案。如果
    [103,1101,3]
    位于
    B
    中,则应将其从输出中排除(该对
    [101,3]
    违反了含义),但我的代码接受了它,因为它在检查含义之前将
    A
    对组合在一起(这取决于
    A
    对匹配)。谢谢,这是完美的工作后,您的编辑!我遇到的一个问题是关于
    m=m.all((1,2))
    。它不断抛出一个
    类型错误:需要一个整数。我只是将它分为
    m=m.all(2)
    m=m.all(1)
    可能是最近引入的功能。我用numpy 1.9.2进行了测试。如果这两个轴的形状只有两个(如示例中所示),如果速度是个问题,我建议不要对
    all
    执行两次调用,而是执行类似
    m=m[…,0]| m[…,1]
    的操作,这相当于
    m.all(-1)
    -1
    ..
    都给出了最后一个轴。还要确保按顺序执行
    m = a == b
    
    left  = m[...,0]
    right = m[...,1]
    m = ~left | right
    
    m = m.all(2)
    
    m = m.all(1)