查找二维数组切片的交集
Find intersection of 2d slices of arrays
我想获取 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]])
我尝试了此处的解决方案 (Implementation of numpy in1d for 2D arrays?),但出现错误,因为我无法将 view
与数组的一部分一起使用。
感谢您的帮助!
如果我理解正确,你可以使用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]])
我将从简化您的规则开始。现在忽略形状,让我们将 A
和 B
视为成对列表。那么你的要求是,如果一对左边的伙伴匹配A
中左边的伙伴之一,那么右边的伙伴也必须匹配。
这是material implication的定义,写成left match → right match
。好的部分是
(x → y)
is true only in the case that 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
仅沿着一个轴(最后一个轴),然后广播以检查与 [=17 中的任何一对的匹配=],然后检查 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
以下是它如何适用于您的系统。
要绕过形状,只需很好地使用广播,然后检查上述是否对行中的所有对都成立。
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
移动([= 中的行18=]),第二个选择 A
中的哪对(两对),第三个选择 B
,最后一个选择 select 每个对中的哪对一对。要概括这一点(如果您事先不知道两者的形状),您可以使用:
a = A[None, :, None, :] # or A.reshape(1, -1, 1, 2)
b = B.reshape(len(B), 1, -1, 2)
其中 -1
允许 A
和 B
中任意数量的对。 2
假设我们正在讨论配对。
现在我们可以得到一组匹配项:
m = a == b
具有 (10, 2, 2, 2)
的形状,再次代表 (i, a_pair, b_pair, partner)
。
接下来我们应用 material 蕴涵的要求,如上所述。为了便于阅读,我们首先将所有左伙伴与右伙伴分开,然后检查条件是否成立。这里有
left = m[...,0]
right = m[...,1]
m = ~left | right
消除最后一个轴 partner
,留下 (i, b_pair)
.
最后,我们要确保规则适用于 B
每一行中的所有对,这由 b_pair
轴 (2) 给出。
m = m.all(2)
当然它必须符合 A
中所有对的匹配(a_pair
轴是 1):
m = m.all(1)
将它们放在一起,并结合最后一步中的 any
调用,您将得到上面的函数。
我想获取 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]])
我尝试了此处的解决方案 (Implementation of numpy in1d for 2D arrays?),但出现错误,因为我无法将 view
与数组的一部分一起使用。
感谢您的帮助!
如果我理解正确,你可以使用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]])
我将从简化您的规则开始。现在忽略形状,让我们将 A
和 B
视为成对列表。那么你的要求是,如果一对左边的伙伴匹配A
中左边的伙伴之一,那么右边的伙伴也必须匹配。
这是material implication的定义,写成left match → right match
。好的部分是
(x → y)
is true only in the case thateither (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
仅沿着一个轴(最后一个轴),然后广播以检查与 [=17 中的任何一对的匹配=],然后检查 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
以下是它如何适用于您的系统。
要绕过形状,只需很好地使用广播,然后检查上述是否对行中的所有对都成立。
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
移动([= 中的行18=]),第二个选择A
中的哪对(两对),第三个选择B
,最后一个选择 select 每个对中的哪对一对。要概括这一点(如果您事先不知道两者的形状),您可以使用:a = A[None, :, None, :] # or A.reshape(1, -1, 1, 2) b = B.reshape(len(B), 1, -1, 2)
其中
-1
允许A
和B
中任意数量的对。2
假设我们正在讨论配对。现在我们可以得到一组匹配项:
m = a == b
具有
(10, 2, 2, 2)
的形状,再次代表(i, a_pair, b_pair, partner)
。接下来我们应用 material 蕴涵的要求,如上所述。为了便于阅读,我们首先将所有左伙伴与右伙伴分开,然后检查条件是否成立。这里有
left = m[...,0] right = m[...,1] m = ~left | right
消除最后一个轴
partner
,留下(i, b_pair)
.最后,我们要确保规则适用于
B
每一行中的所有对,这由b_pair
轴 (2) 给出。m = m.all(2)
当然它必须符合
A
中所有对的匹配(a_pair
轴是 1):m = m.all(1)
将它们放在一起,并结合最后一步中的 any
调用,您将得到上面的函数。