【问题标题】:Finding intersection of two matrices in Python within a tolerance?在公差范围内找到 Python 中两个矩阵的交集?
【发布时间】:2016-02-04 10:29:08
【问题描述】:

我正在寻找找到两个不同大小矩阵的交集的最有效方法。每个矩阵都有三个变量(列)和不同数量的观察值(行)。比如矩阵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')

如果我将每列的容差设置为 col1 = 1col2 = 2col3 = 10,我需要一个函数,以便它输出在各自范围内的 ab 中的索引容差,例如:

[x1, x2] = func(a, b, col1, col2, col3)
print x1
>> [2 3]
print x2
>> [1 3]

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

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

对于完成此任务的循环方法的替代方法有什么建议吗?

【问题讨论】:

    标签: python numpy matrix vectorization intersection


    【解决方案1】:

    如果您不介意使用 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))
    

    示例运行 -

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

    大数据大小案例:如果您正在处理导致内存问题的大数据大小,并且由于您已经知道列数很少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)
    

    【讨论】:

    • 这太棒了,而且比for 循环快得多。我不熟悉[:,None] 命名法;超级有帮助。谢谢!
    • @user1566200 查看有关巨大数据大小案例的编辑。
    • @Divakar 感谢您花时间提供帮助。我的数据集是 866,000 行。它不会让我创建一个 866,000 x 866,000 的矩阵(在np.ones() 步骤中)。仍然是 MemoryError
    • @user1566200 嗯,我想在这种情况下,您需要沿行遍历任一输入数组。
    猜你喜欢
    • 2012-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多