Python 带有';行';和索引

Python 带有';行';和索引,python,matlab,numpy,Python,Matlab,Numpy,有人问过类似的问题,但没有一个答案完全符合我的需要——有些答案允许多维搜索(在matlab中称为“行”选项),但不返回索引。有些返回索引,但不允许行。我的阵列非常大(1米x 2),我成功地制作了一个可以工作的循环,但显然速度非常慢。在matlab中,内置的ismember函数大约需要10秒 以下是我想要的: a=np.array([[4, 6],[2, 6],[5, 2]]) b=np.array([[1, 7],[1, 8],[2, 6],[2, 1],[2, 4],[4, 6],[4, 7

有人问过类似的问题,但没有一个答案完全符合我的需要——有些答案允许多维搜索(在matlab中称为“行”选项),但不返回索引。有些返回索引,但不允许行。我的阵列非常大(1米x 2),我成功地制作了一个可以工作的循环,但显然速度非常慢。在matlab中,内置的ismember函数大约需要10秒

以下是我想要的:

a=np.array([[4, 6],[2, 6],[5, 2]])

b=np.array([[1, 7],[1, 8],[2, 6],[2, 1],[2, 4],[4, 6],[4, 7],[5, 9],[5, 2],[5, 1]])
实现此功能的确切matlab函数是:

[~,index] = ismember(a,b,'rows')
在哪里

index = [6, 3, 9] 
印刷品

[2 5 8]
这相当于Matlab的[3,6,9],因为Python使用基于0的索引

一些警告:

  • 索引按递增顺序返回。它们不对应 到
    b
    a
    项的位置
  • asvoid适用于整数数据类型,但如果使用asvoid,请小心 在浮点数据类型上,因为
    asvoid([-0.])==asvoid([0.])
    返回
    数组([False])
  • asvoid最适合于连续数组。如果数组不连续,数据将被复制到连续数组,这将降低性能

  • 尽管有这些警告,出于速度的考虑,人们还是可以选择在D_索引中使用

    def ismember_rows(a, b):
        # http://stackoverflow.com/a/22705773/190597 (ashg)
        return np.nonzero(np.all(b == a[:,np.newaxis], axis=2))[1]
    
    In [41]: a2 = np.tile(a,(2000,1))
    In [42]: b2 = np.tile(b,(2000,1))
    
    In [46]: %timeit in1d_index(a2, b2)
    100 loops, best of 3: 8.49 ms per loop
    
    In [47]: %timeit ismember_rows(a2, b2)
    1 loops, best of 3: 5.55 s per loop
    
    因此,
    in1d_索引
    快了约6500倍(对于长度较低的数千个数组),但再次注意,这种比较并不完全一致,因为
    in1d_索引
    按递增顺序返回索引,而
    ismember_行
    a
    的顺序返回索引,显示在
    b

    import numpy as np 
    def ismember_rows(a, b):
        '''Equivalent of 'ismember' from Matlab
        a.shape = (nRows_a, nCol)
        b.shape = (nRows_b, nCol)
        return the idx where b[idx] == a
        '''
        return np.nonzero(np.all(b == a[:,np.newaxis], axis=2))[1]
    
    a = np.array([[4, 6],[2, 6],[5, 2]])
    b = np.array([[1, 7],[1, 8],[2, 6],[2, 1],[2, 4],[4, 6],[4, 7],[5, 9],[5, 2],[5, 1]])
    idx = ismember_rows(a, b)
    print idx
    print np.all(b[idx] == a)
    
    印刷品

    e、 …我用过广播

    --------------------------[更新]------------------------------

    def ismember(a, b):
        return np.flatnonzero(np.in1d(b[:,0], a[:,0]) & np.in1d(b[:,1], a[:,1]))
    
    a = np.array([[4, 6],[2, 6],[5, 2]])
    b = np.array([[1, 7],[1, 8],[2, 6],[2, 1],[2, 4],[4, 6],[4, 7],[5, 9],[5, 2],[5, 1]])
    a2 = np.tile(a,(2000,1))
    b2 = np.tile(b,(2000,1))
    
    %timeit timeit in1d_index(a2, b2)
    # 100 loops, best of 3: 8.74 ms per loop
    %timeit ismember(a2, b2)
    # 100 loops, best of 3: 8.5 ms per loop
    
    np.all(in1d_index(a2, b2) == ismember(a2, b2))
    # True
    

    正如unutbu所说,索引是按递增顺序返回的。函数首先将多列元素转换为单列数组,然后使用numpy.in1d查找所需答案,请尝试以下代码:

    import numpy as np
    
    def ismemberRow(A,B):
        '''
        This function is find which rows found in A can be also found in B,
        The function first turns multiple columns of elements into a single column array, then numpy.in1d can be used
    
        Input: m x n numpy array (A), and p x q array (B)
        Output unique numpy array with length m, storing either True or False, True for rows can be found in both A and B
        '''
    
        sa = np.chararray((A.shape[0],1))
        sa[:] = '-'
        sb = np.chararray((B.shape[0],1))
        sb[:] = '-'
    
        ba = (A).astype(np.str)
        sa2 = np.expand_dims(ba[:,0],axis=1) + sa + np.expand_dims(ba[:,1],axis=1)
        na = A.shape[1] - 2    
    
        for i in range(0,na):
             sa2 = sa2 + sa + np.expand_dims(ba[:,i+2],axis=1)
    
        bb = (B).astype(np.str)
        sb2 = np.expand_dims(bb[:,0],axis=1) + sb + np.expand_dims(bb[:,1],axis=1)
        nb = B.shape[1] - 2    
    
        for i in range(0,nb):
             sb2 = sb2 + sb + np.expand_dims(bb[:,i+2],axis=1)
    
        return np.in1d(sa2,sb2)
    
    A = np.array([[1, 3, 4],[2, 4, 3],[7, 4, 3],[1, 1, 1],[1, 3, 4],[5, 3, 4],[1, 1, 1],[2, 4, 3]])
    
    B = np.array([[1, 3, 4],[1, 1, 1]])
    
    d = ismemberRow(A,B)
    
    print A[np.where(d)[0],:]
    
    #results:
    #[[1 3 4]
    # [1 1 1]
    # [1 3 4]
    # [1 1 1]]
    

    阵列的数据类型是什么?
    a
    b
    的长度是否都在1M左右?
    索引
    中的值顺序对您重要吗?它们都是数据类型('int64')。b的长度约为1M,a的长度约为750k。a中的每个条目都将在b中,但不是相反。理想情况下,索引输出的长度应与b相同,b的值显示a中的索引。。。我的意思是输出的长度应该与a相同。反过来说也没什么意义。谢谢你的建议。我不会使用连续数组,但是我可以先对a进行排序(假设我也可以获得排序的索引,这可能是argsort实现的吗?),然后我可以按照您的建议进行操作。您可能希望看到在没有任何特殊操作的情况下,
    inAD_index
    如何执行。
    arr=np.ascontiguousarray(arr)
    将使输入连续(如果它们尚未连续)。我尝试运行此命令,但不幸的是,它杀死了我的内核。我有非常大的阵列。。。
    def ismember(a, b):
        return np.flatnonzero(np.in1d(b[:,0], a[:,0]) & np.in1d(b[:,1], a[:,1]))
    
    a = np.array([[4, 6],[2, 6],[5, 2]])
    b = np.array([[1, 7],[1, 8],[2, 6],[2, 1],[2, 4],[4, 6],[4, 7],[5, 9],[5, 2],[5, 1]])
    a2 = np.tile(a,(2000,1))
    b2 = np.tile(b,(2000,1))
    
    %timeit timeit in1d_index(a2, b2)
    # 100 loops, best of 3: 8.74 ms per loop
    %timeit ismember(a2, b2)
    # 100 loops, best of 3: 8.5 ms per loop
    
    np.all(in1d_index(a2, b2) == ismember(a2, b2))
    # True
    
    import numpy as np
    
    def ismemberRow(A,B):
        '''
        This function is find which rows found in A can be also found in B,
        The function first turns multiple columns of elements into a single column array, then numpy.in1d can be used
    
        Input: m x n numpy array (A), and p x q array (B)
        Output unique numpy array with length m, storing either True or False, True for rows can be found in both A and B
        '''
    
        sa = np.chararray((A.shape[0],1))
        sa[:] = '-'
        sb = np.chararray((B.shape[0],1))
        sb[:] = '-'
    
        ba = (A).astype(np.str)
        sa2 = np.expand_dims(ba[:,0],axis=1) + sa + np.expand_dims(ba[:,1],axis=1)
        na = A.shape[1] - 2    
    
        for i in range(0,na):
             sa2 = sa2 + sa + np.expand_dims(ba[:,i+2],axis=1)
    
        bb = (B).astype(np.str)
        sb2 = np.expand_dims(bb[:,0],axis=1) + sb + np.expand_dims(bb[:,1],axis=1)
        nb = B.shape[1] - 2    
    
        for i in range(0,nb):
             sb2 = sb2 + sb + np.expand_dims(bb[:,i+2],axis=1)
    
        return np.in1d(sa2,sb2)
    
    A = np.array([[1, 3, 4],[2, 4, 3],[7, 4, 3],[1, 1, 1],[1, 3, 4],[5, 3, 4],[1, 1, 1],[2, 4, 3]])
    
    B = np.array([[1, 3, 4],[1, 1, 1]])
    
    d = ismemberRow(A,B)
    
    print A[np.where(d)[0],:]
    
    #results:
    #[[1 3 4]
    # [1 1 1]
    # [1 3 4]
    # [1 1 1]]