(Python) 找出两个数组中与其他两个数组中的值相等的值的索引
(Python) Find the indices of the values in two arrays that are equal to the values in two other arrays
我有以下 4 个数组,我想获取数组 A 和 X 中相等的值的索引,这些值对应于 B 和 Y 中相同位置的值。因此对于以下示例,
import numpy as np
A = np.asarray([400.5, 100, 700, 200, 15, 900])
B = np.asarray([500.5, 200, 500, 600.5, 8, 999])
X = np.asarray([400.5, 700, 100, 300, 15, 555, 900])
Y = np.asarray([500.5, 500,600.5, 100, 8, 555, 999])
我想得到两个索引数组:
indAB = [0 2 4 5]
- 0因为A&B中的400.5和500.5也在X&Y的位置0
- 2因为A&B中的700和500也在位置2的X&Y中
- 4因为A&B中的15和8也在X&Y的位置4
- 5因为A&B中的900和999也在X&Y的位置5
indXY = [0 1 4 6]
- 0、1、4 和 6 与 indAB 相似,但与 X&Y 相关。
其中 indAB 是 A 和 B 中与 X 和 Y 中的值相等的值的索引,indXY 是 X 和 Y 中等于 A 和 B 中的值的值的索引。
这是我目前的尝试:
def indices(a,b):
setb = set(b)
ind = [i for i, x in enumerate(a) if x in setb]
return ind
iA = np.asarray(indices(A,X))
iB = np.asarray(indices(X,A))
iX = np.asarray(indices(B,Y))
iY = np.asarray(indices(Y,B))
def CommonIndices(a,b):
return np.asarray(list(set(a) & set(b)))
indAB = CommonIndices(iA,iX)
indXY = CommonIndices(iB,iY)
print(indAB) # returns = [0 2 4 5]
print(indXY) # returns = [0 1 2 4 6]
我一直得到 indXY 的 [0 1 2 4 6],这是不正确的。不应包括 2,因为即使 Y 和 B 中有 600.5,A 和 B 中的 200 和 100(分别)不相等。
如果有人能提供解决方案,我将不胜感激。非常感谢!
试试这个:
import numpy as np
A = np.asarray([400.5, 100, 700, 200, 15, 900])
B = np.asarray([500.5, 200, 500, 600.5, 8, 999])
X = np.asarray([400.5, 700, 100, 300, 15, 555, 900])
Y = np.asarray([500.5, 500,600.5, 100, 8, 555, 999])
AB = np.stack([A, B], axis=-1)
XY = np.stack([X, Y], axis=-1)
eq = AB[:, np.newaxis, :] == XY[np.newaxis, :, :]
eq = np.logical_and.reduce(eq, axis=-1)
indAB, = np.where(np.logical_or.reduce(eq, axis=1))
indXY, = np.where(np.logical_or.reduce(eq, axis=0))
print("indAB", indAB)
print("indXY", indXY)
输出:
indAB [0 2 4 5]
indXY [0 1 4 6]
说明
AB
和XY
只是数组A
和B
和X
和Y
分别"stacked"二维数组。 eq
保存 AB
和 XY
中元素的全对所有比较; np.newaxis
用于向 AB
和 XY
添加维度(注意 AB
在位置 1 和 XY
在位置 0 获得新维度)。相等运算符 ==
通过数组的新维度广播数组。第一个np.logical_and.reduce
是保证两个"components"相等(A
到X
和B
到Y
),np.logical_or.reduce
操作检查是否存在从 AB
到 XY
和从 XY
到 AB
的完全等式。最后,np.where
获取索引。
作为缺点,请注意这需要一个大小为 len(A)
x len(X)
x 2 的布尔数组,因此如果原始数组 非常 大你可能 运行 遇到内存问题。
更新
如前所述,非常大的数组可能是个问题。如果你想进行所有比较 "in one go" 并没有真正的解决方法(中间数组的大小只是比较的数量)。但是,您也可以 运行 算法 "by pieces",例如这样的东西:
import numpy as np
MAX_SIZE = 2 # Biggest array will be MAX_SIZE x MAX_SIZE x 2
A = np.asarray([400.5, 100, 700, 200, 15, 900])
B = np.asarray([500.5, 200, 500, 600.5, 8, 999])
X = np.asarray([400.5, 700, 100, 300, 15, 555, 900])
Y = np.asarray([500.5, 500,600.5, 100, 8, 555, 999])
AB = np.stack([A, B], axis=-1)
XY = np.stack([X, Y], axis=-1)
maskAB = np.full(len(AB), False, dtype=bool)
maskXY = np.full(len(XY), False, dtype=bool)
for iAB in range(0, len(AB), MAX_SIZE):
pAB = np.expand_dims(AB[iAB:iAB + MAX_SIZE], axis=1)
for iXY in range(0, len(XY), MAX_SIZE):
pXY = np.expand_dims(XY[iXY:iXY + MAX_SIZE], axis=0)
eq = pAB == pXY
eq = np.logical_and.reduce(eq, axis=-1)
maskAB[iAB:iAB + MAX_SIZE] |= np.logical_or.reduce(eq, axis=1)
maskXY[iXY:iXY + MAX_SIZE] |= np.logical_or.reduce(eq, axis=0)
indAB, = np.where(maskAB)
indXY, = np.where(maskXY)
print("indAB", indAB)
print("indXY", indXY)
输出仍然是:
indAB [0 2 4 5]
indXY [0 1 4 6]
我使用 2 的 MAX_SIZE
只是为了表明它在示例中有效,但实际上您可以根据您愿意使用的最大内存量来选择它(例如 MAX_SIZE = 10000
应该是百兆左右)。 MAX_SIZE
不需要 数组的大小,也不必是数组大小的除数。
numpy_indexed 包(免责声明:我是它的作者)包含高效优雅地完成此类事情的功能。此方法的内存要求是线性的,计算要求为 NlogN。对于您正在考虑的大量阵列,相对于当前接受的蛮力方法的速度优势很容易达到几个数量级:
import numpy as np
import numpy_indexed as npi
A = np.asarray([400.5, 100, 700, 200, 15, 900])
B = np.asarray([500.5, 200, 500, 600.5, 8, 999])
X = np.asarray([400.5, 700, 100, 300, 15, 555, 900])
Y = np.asarray([500.5, 500,600.5, 100, 8, 555, 999])
AB = np.stack([A, B], axis=-1)
XY = np.stack([X, Y], axis=-1)
# casting the AB and XY arrays to npi.index first is not required, but a performance optimization; without this each call to npi.indices would have to re-index the arrays, which is the expensive part
AB = npi.as_index(AB)
XY = npi.as_index(XY)
# npi.indices(list, items) is a vectorized nd-equivalent of list.index(item)
indAB = npi.indices(AB, XY, missing='mask').compressed()
indXY = npi.indices(XY, AB, missing='mask').compressed()
请注意,您也可以选择如何处理缺失值。还要看一下集合操作,例如 npi.intersection(XY, AB);他们可能会提供更简单的途径,帮助您实现更高层次的目标。
这是另一种方法。我敢说比较清楚,由于使用集合,它应该是高效的,它只需要 O( len(A) + len(X) )
内存。
numpy
甚至不需要,但可以用于数组。
from collections import defaultdict
A = [400.5, 100, 700, 200, 15, 900]
B = [500.5, 200, 500, 600.5, 8, 999]
X = [400.5, 700, 100, 300, 15, 555, 900]
Y = [500.5, 500, 600.5, 100, 8, 555, 999]
def get_indices(values):
d = defaultdict(set)
for i, value in enumerate(values):
d[value].add(i)
return d
iA, iB, iX, iY = [get_indices(values) for values in [A, B, X, Y]]
print(iA)
# {400.5: {0}, 100: {1}, 200: {3}, 900: {5}, 700: {2}, 15: {4}}
print(iX)
# {400.5: {0}, 100: {2}, 300: {3}, 900: {6}, 555: {5}, 700: {1}, 15: {4}}
for i, (a, b) in enumerate(zip(A, B)):
common_indices = iX[a] & iY[b]
if common_indices:
print("A B : %d" % i)
print("X Y : %d" % common_indices.pop())
print()
# A B : 0
# X Y : 0
# A B : 2
# X Y : 1
# A B : 4
# X Y : 4
# A B : 5
# X Y : 6
我有以下 4 个数组,我想获取数组 A 和 X 中相等的值的索引,这些值对应于 B 和 Y 中相同位置的值。因此对于以下示例,
import numpy as np
A = np.asarray([400.5, 100, 700, 200, 15, 900])
B = np.asarray([500.5, 200, 500, 600.5, 8, 999])
X = np.asarray([400.5, 700, 100, 300, 15, 555, 900])
Y = np.asarray([500.5, 500,600.5, 100, 8, 555, 999])
我想得到两个索引数组:
indAB = [0 2 4 5]
- 0因为A&B中的400.5和500.5也在X&Y的位置0
- 2因为A&B中的700和500也在位置2的X&Y中
- 4因为A&B中的15和8也在X&Y的位置4
- 5因为A&B中的900和999也在X&Y的位置5
indXY = [0 1 4 6]
- 0、1、4 和 6 与 indAB 相似,但与 X&Y 相关。
其中 indAB 是 A 和 B 中与 X 和 Y 中的值相等的值的索引,indXY 是 X 和 Y 中等于 A 和 B 中的值的值的索引。
这是我目前的尝试:
def indices(a,b):
setb = set(b)
ind = [i for i, x in enumerate(a) if x in setb]
return ind
iA = np.asarray(indices(A,X))
iB = np.asarray(indices(X,A))
iX = np.asarray(indices(B,Y))
iY = np.asarray(indices(Y,B))
def CommonIndices(a,b):
return np.asarray(list(set(a) & set(b)))
indAB = CommonIndices(iA,iX)
indXY = CommonIndices(iB,iY)
print(indAB) # returns = [0 2 4 5]
print(indXY) # returns = [0 1 2 4 6]
我一直得到 indXY 的 [0 1 2 4 6],这是不正确的。不应包括 2,因为即使 Y 和 B 中有 600.5,A 和 B 中的 200 和 100(分别)不相等。
如果有人能提供解决方案,我将不胜感激。非常感谢!
试试这个:
import numpy as np
A = np.asarray([400.5, 100, 700, 200, 15, 900])
B = np.asarray([500.5, 200, 500, 600.5, 8, 999])
X = np.asarray([400.5, 700, 100, 300, 15, 555, 900])
Y = np.asarray([500.5, 500,600.5, 100, 8, 555, 999])
AB = np.stack([A, B], axis=-1)
XY = np.stack([X, Y], axis=-1)
eq = AB[:, np.newaxis, :] == XY[np.newaxis, :, :]
eq = np.logical_and.reduce(eq, axis=-1)
indAB, = np.where(np.logical_or.reduce(eq, axis=1))
indXY, = np.where(np.logical_or.reduce(eq, axis=0))
print("indAB", indAB)
print("indXY", indXY)
输出:
indAB [0 2 4 5]
indXY [0 1 4 6]
说明
AB
和XY
只是数组A
和B
和X
和Y
分别"stacked"二维数组。 eq
保存 AB
和 XY
中元素的全对所有比较; np.newaxis
用于向 AB
和 XY
添加维度(注意 AB
在位置 1 和 XY
在位置 0 获得新维度)。相等运算符 ==
通过数组的新维度广播数组。第一个np.logical_and.reduce
是保证两个"components"相等(A
到X
和B
到Y
),np.logical_or.reduce
操作检查是否存在从 AB
到 XY
和从 XY
到 AB
的完全等式。最后,np.where
获取索引。
作为缺点,请注意这需要一个大小为 len(A)
x len(X)
x 2 的布尔数组,因此如果原始数组 非常 大你可能 运行 遇到内存问题。
更新
如前所述,非常大的数组可能是个问题。如果你想进行所有比较 "in one go" 并没有真正的解决方法(中间数组的大小只是比较的数量)。但是,您也可以 运行 算法 "by pieces",例如这样的东西:
import numpy as np
MAX_SIZE = 2 # Biggest array will be MAX_SIZE x MAX_SIZE x 2
A = np.asarray([400.5, 100, 700, 200, 15, 900])
B = np.asarray([500.5, 200, 500, 600.5, 8, 999])
X = np.asarray([400.5, 700, 100, 300, 15, 555, 900])
Y = np.asarray([500.5, 500,600.5, 100, 8, 555, 999])
AB = np.stack([A, B], axis=-1)
XY = np.stack([X, Y], axis=-1)
maskAB = np.full(len(AB), False, dtype=bool)
maskXY = np.full(len(XY), False, dtype=bool)
for iAB in range(0, len(AB), MAX_SIZE):
pAB = np.expand_dims(AB[iAB:iAB + MAX_SIZE], axis=1)
for iXY in range(0, len(XY), MAX_SIZE):
pXY = np.expand_dims(XY[iXY:iXY + MAX_SIZE], axis=0)
eq = pAB == pXY
eq = np.logical_and.reduce(eq, axis=-1)
maskAB[iAB:iAB + MAX_SIZE] |= np.logical_or.reduce(eq, axis=1)
maskXY[iXY:iXY + MAX_SIZE] |= np.logical_or.reduce(eq, axis=0)
indAB, = np.where(maskAB)
indXY, = np.where(maskXY)
print("indAB", indAB)
print("indXY", indXY)
输出仍然是:
indAB [0 2 4 5]
indXY [0 1 4 6]
我使用 2 的 MAX_SIZE
只是为了表明它在示例中有效,但实际上您可以根据您愿意使用的最大内存量来选择它(例如 MAX_SIZE = 10000
应该是百兆左右)。 MAX_SIZE
不需要 数组的大小,也不必是数组大小的除数。
numpy_indexed 包(免责声明:我是它的作者)包含高效优雅地完成此类事情的功能。此方法的内存要求是线性的,计算要求为 NlogN。对于您正在考虑的大量阵列,相对于当前接受的蛮力方法的速度优势很容易达到几个数量级:
import numpy as np
import numpy_indexed as npi
A = np.asarray([400.5, 100, 700, 200, 15, 900])
B = np.asarray([500.5, 200, 500, 600.5, 8, 999])
X = np.asarray([400.5, 700, 100, 300, 15, 555, 900])
Y = np.asarray([500.5, 500,600.5, 100, 8, 555, 999])
AB = np.stack([A, B], axis=-1)
XY = np.stack([X, Y], axis=-1)
# casting the AB and XY arrays to npi.index first is not required, but a performance optimization; without this each call to npi.indices would have to re-index the arrays, which is the expensive part
AB = npi.as_index(AB)
XY = npi.as_index(XY)
# npi.indices(list, items) is a vectorized nd-equivalent of list.index(item)
indAB = npi.indices(AB, XY, missing='mask').compressed()
indXY = npi.indices(XY, AB, missing='mask').compressed()
请注意,您也可以选择如何处理缺失值。还要看一下集合操作,例如 npi.intersection(XY, AB);他们可能会提供更简单的途径,帮助您实现更高层次的目标。
这是另一种方法。我敢说比较清楚,由于使用集合,它应该是高效的,它只需要 O( len(A) + len(X) )
内存。
numpy
甚至不需要,但可以用于数组。
from collections import defaultdict
A = [400.5, 100, 700, 200, 15, 900]
B = [500.5, 200, 500, 600.5, 8, 999]
X = [400.5, 700, 100, 300, 15, 555, 900]
Y = [500.5, 500, 600.5, 100, 8, 555, 999]
def get_indices(values):
d = defaultdict(set)
for i, value in enumerate(values):
d[value].add(i)
return d
iA, iB, iX, iY = [get_indices(values) for values in [A, B, X, Y]]
print(iA)
# {400.5: {0}, 100: {1}, 200: {3}, 900: {5}, 700: {2}, 15: {4}}
print(iX)
# {400.5: {0}, 100: {2}, 300: {3}, 900: {6}, 555: {5}, 700: {1}, 15: {4}}
for i, (a, b) in enumerate(zip(A, B)):
common_indices = iX[a] & iY[b]
if common_indices:
print("A B : %d" % i)
print("X Y : %d" % common_indices.pop())
print()
# A B : 0
# X Y : 0
# A B : 2
# X Y : 1
# A B : 4
# X Y : 4
# A B : 5
# X Y : 6