在公差范围内找到两个矩阵的交集?

use*_*200 4 python numpy intersection matrix vectorization

我正在寻找找到两个不同大小的矩阵的交集的最有效方法。每个矩阵都有三个变量(列)和不同数量的观察值(行)。例如,矩阵A:

a = np.matrix('1 5 1003; 2 4 1002; 4 3 1008; 8 1 2005')
b = np.matrix('7 9 1006; 4 4 1007; 7 7 1050; 8 2 2003'; 9 9 3000; 7 7 1000')
Run Code Online (Sandbox Code Playgroud)

如果我将每列的公差设置为col1 = 1,,col2 = 2col3 = 10,则需要一个函数,使其输出in a和in b分别在各自公差之内,例如:

[x1, x2] = func(a, b, col1, col2, col3)
print x1
>> [2 3]
print x2
>> [1 3]
Run Code Online (Sandbox Code Playgroud)

您可以通过索引看到的元素2 a在的元素1的公差内b

我想我可以遍历矩阵的每个元素a,检查它是否在的每个元素的公差范围内b,然后这样做。但是,对于非常大的数据集而言,效率似乎很低。

对实现此目标的循环方法的替代方案有何建议?

Div*_*kar 5

如果您不介意使用NumPy数组,则可以利用broadcasting矢量化解决方案。这是实现-

# Set tolerance values for each column
tol = [1, 2, 10]

# Get absolute differences between a and b keeping their columns aligned
diffs = np.abs(np.asarray(a[:,None]) - np.asarray(b))

# Compare each row with the triplet from `tol`.
# Get mask of all matching rows and finally get the matching indices
x1,x2 = np.nonzero((diffs < tol).all(2))
Run Code Online (Sandbox Code Playgroud)

样品运行-

In [46]: # Inputs
    ...: a=np.matrix('1 5 1003; 2 4 1002; 4 3 1008; 8 1 2005')
    ...: b=np.matrix('7 9 1006; 4 4 1007; 7 7 1050; 8 2 2003; 9 9 3000; 7 7 1000')
    ...: 

In [47]: # Set tolerance values for each column
    ...: tol = [1, 2, 10]
    ...: 
    ...: # Get absolute differences between a and b keeping their columns aligned
    ...: diffs = np.abs(np.asarray(a[:,None]) - np.asarray(b))
    ...: 
    ...: # Compare each row with the triplet from `tol`.
    ...: # Get mask of all matching rows and finally get the matching indices
    ...: x1,x2 = np.nonzero((diffs < tol).all(2))
    ...: 

In [48]: x1,x2
Out[48]: (array([2, 3]), array([1, 3]))
Run Code Online (Sandbox Code Playgroud)

大型数据大小的情况:如果您正在使用会导致内存问题的大型数据大小,并且由于您已经知道列数很小3,则可能需要最小的3迭代循环并节省大量内存,例如-

na = a.shape[0]
nb = b.shape[0]
accum = np.ones((na,nb),dtype=bool)
for i in range(a.shape[1]):
    accum &=  np.abs((a[:,i] - b[:,i].ravel())) < tol[i]
x1,x2 = np.nonzero(accum)
Run Code Online (Sandbox Code Playgroud)