Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从子阵中的numpy 2D数组中提取相交数组的索引_Python_Arrays_Numpy_Intersection - Fatal编程技术网

Python 从子阵中的numpy 2D数组中提取相交数组的索引

Python 从子阵中的numpy 2D数组中提取相交数组的索引,python,arrays,numpy,intersection,Python,Arrays,Numpy,Intersection,我有两个2D numpy方形数组,A和B。B是从A中提取的数组,其中有一定数量的列和行(具有相同的索引)被剥离。它们都是对称的。例如,A和B可以是: A = np.array([[1,2,3,4,5], [2,7,8,9,10], [3,8,13,14,15], [4,9,14,19,20], [5,10,15,20,25]]) B = np.array([[1,3,5],

我有两个2D numpy方形数组,A和B。B是从A中提取的数组,其中有一定数量的列和行(具有相同的索引)被剥离。它们都是对称的。例如,A和B可以是:

A = np.array([[1,2,3,4,5],
              [2,7,8,9,10],
              [3,8,13,14,15],
              [4,9,14,19,20],
              [5,10,15,20,25]])
B = np.array([[1,3,5],
              [3,13,15],
              [5,15,25]])
使得缺失索引为[1,3],相交索引为[0,2,4]

是否有一种“智能”方法来提取a中的索引,对应于B中存在的行/列,它涉及高级索引等?我能想到的就是:

        import numpy as np
        index = np.array([],dtype=int)
        n,m = len(A),len(B)
        for j in range(n):
            k = 0
            while set(np.intersect1d(B[j],A[k])) != set(B[j]) and k<m:
                k+=1
            np.append(index,k)
将numpy导入为np
index=np.array([],dtype=int)
n、 m=len(A),len(B)
对于范围(n)内的j:
k=0

而集(np.intersect1d(B[j],A[k])!=set(B[j])和k考虑当所有值都不同时的简单情况:

A = np.arange(25).reshape(5,5)
ans = [1,3,4]
B = A[np.ix_(ans, ans)]

In [287]: A
Out[287]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

In [288]: B
Out[288]: 
array([[ 6,  8,  9],
       [16, 18, 19],
       [21, 23, 24]])
如果我们用A的每一行测试B的第一行,我们最终会得到 将
[6,8,9]
[5,6,7,8,9]
进行比较,我们可以从中收集 索引的候选解决方案
[1,3,4]

我们可以通过首先配对来生成一组所有可能的候选解 B的第行和A的每一行

如果只有一个候选人,那么我们就完蛋了,因为我们知道B是a A的子矩阵,因此总有一个解

如果有不止一个候选人,那么我们可以对候选人做同样的事情 B的第二行,并取候选解的交点-- 总之,a解决方案必须是B的每一行的解决方案

因此,我们可以在B行中循环,并在找到B行时短路 只有一位候选人。同样,我们假设B总是a的子矩阵

下面的
find_idx
函数实现了上述思想:

import itertools as IT
import numpy as np

def find_idx_1d(rowA, rowB):
    result = []
    if np.in1d(rowB, rowA).all():
        result = [tuple(sorted(idx)) 
                  for idx in IT.product(*[np.where(rowA==b)[0] for b in rowB])]
    return result

def find_idx(A, B):
    candidates = set([idx for row in A for idx in find_idx_1d(row, B[0])])
    for Bi in B[1:]:
        if len(candidates) == 1:
            # stop when there is a unique candidate
            return candidates.pop()
        new = [idx for row in A for idx in find_idx_1d(row, Bi)]  
        candidates = candidates.intersection(new)
    if candidates:
        return candidates.pop()
    raise ValueError('no solution found')

正确性:您提出的两种解决方案可能并不总是返回正确的结果,尤其是当存在重复值时。比如说,

def is_solution(A, B, idx):
    return np.allclose(A[np.ix_(idx, idx)], B)

def find_idx_orig(A, B):
    index = []
    for j in range(len(B)):
        k = 0
        while k<len(A) and set(np.intersect1d(B[j],A[k])) != set(B[j]):
            k+=1
        index.append(k)
    return index

def find_idx_diag(A, B):
    index = []
    a = np.diag(A)
    b = np.diag(B)
    for j in range(len(b)):
        k = 0
        while a[j+k] != b[j] and k<len(A):
            k+=1
        index.append(k+j)
    return index

def counterexample():
    """
    Show find_idx_diag, find_idx_orig may not return the correct result
    """
    A = np.array([[1,2,0],
                  [2,1,0],
                  [0,0,1]])
    ans = [0,1]
    B = A[np.ix_(ans, ans)]
    assert not is_solution(A, B, find_idx_orig(A, B))
    assert is_solution(A, B, find_idx(A, B))

    A = np.array([[1,2,0],
                  [2,1,0],
                  [0,0,1]])
    ans = [1,2]
    B = A[np.ix_(ans, ans)]

    assert not is_solution(A, B, find_idx_diag(A, B))
    assert is_solution(A, B, find_idx(A, B))

counterexample()
因此
find_idx
find_idx_orig
快得多,但速度不如
find_idx_diag

这应该类似于matlab函数ismember。看看这个。在一个表中有重复的值吗?总是有一个唯一的答案吗?(例如,如果A是全1怎么办?@unutbu是的,A中可以有重复的值,是的,答案应该是唯一的。两个矩阵都应该足够大,以便所有的列或行向量都不同。@Bort我还能在二维数组上使用
np.searchsorted
?B中的列和行都不等于A。A有多大?(最快的方法可能取决于尺寸。)感谢您的详细回答!您的解决方案只比我的略慢,但总是正确的,所以我将切换到它。
def is_solution(A, B, idx):
    return np.allclose(A[np.ix_(idx, idx)], B)

def find_idx_orig(A, B):
    index = []
    for j in range(len(B)):
        k = 0
        while k<len(A) and set(np.intersect1d(B[j],A[k])) != set(B[j]):
            k+=1
        index.append(k)
    return index

def find_idx_diag(A, B):
    index = []
    a = np.diag(A)
    b = np.diag(B)
    for j in range(len(b)):
        k = 0
        while a[j+k] != b[j] and k<len(A):
            k+=1
        index.append(k+j)
    return index

def counterexample():
    """
    Show find_idx_diag, find_idx_orig may not return the correct result
    """
    A = np.array([[1,2,0],
                  [2,1,0],
                  [0,0,1]])
    ans = [0,1]
    B = A[np.ix_(ans, ans)]
    assert not is_solution(A, B, find_idx_orig(A, B))
    assert is_solution(A, B, find_idx(A, B))

    A = np.array([[1,2,0],
                  [2,1,0],
                  [0,0,1]])
    ans = [1,2]
    B = A[np.ix_(ans, ans)]

    assert not is_solution(A, B, find_idx_diag(A, B))
    assert is_solution(A, B, find_idx(A, B))

counterexample()
def make_AB(n, m):
    A = symmetrize(np.random.random((n, n)))
    ans = np.sort(np.random.choice(n, m, replace=False))
    B = A[np.ix_(ans, ans)]
    return A, B

def symmetrize(a):
    "http://stackoverflow.com/a/2573982/190597 (EOL)"
    return a + a.T - np.diag(a.diagonal())

if __name__ == '__main__':
    counterexample()
    A, B = make_AB(500, 450)
    assert is_solution(A, B, find_idx(A, B))

In [283]: %timeit find_idx(A, B)
10 loops, best of 3: 74 ms per loop

In [284]: %timeit find_idx_orig(A, B)
1 loops, best of 3: 14.5 s per loop

In [285]: %timeit find_idx_diag(A, B)
100 loops, best of 3: 2.93 ms per loop