带有“rows”和index的ismember的Python版本

2024-09-28 20:15:17 发布

您现在位置:Python中文网/ 问答频道 /正文

有人问过类似的问题,但没有一个答案能满足我的需要——有些答案允许多维搜索(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函数是:

^{pr2}$

在哪里

index = [6, 3, 9] 

Tags: 函数答案index选项np数组array内置
3条回答

该函数首先将多个元素列转换为一个列数组,然后数字1英寸可以用来找出想要的答案,请尝试以下代码:

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

打印

^{pr2}$

我用广播

[更新]

^{3}$

正如unutbu所说,指数是按递增顺序返回的

import numpy as np

def asvoid(arr):
    """
    View the array as dtype np.void (bytes)
    This views the last axis of ND-arrays as bytes so you can perform comparisons on
    the entire row.
    http://stackoverflow.com/a/16840350/190597 (Jaime, 2013-05)
    Warning: When using asvoid for comparison, note that float zeros may compare UNEQUALLY
    >>> asvoid([-0.]) == asvoid([0.])
    array([False], dtype=bool)
    """
    arr = np.ascontiguousarray(arr)
    return arr.view(np.dtype((np.void, arr.dtype.itemsize * arr.shape[-1])))


def in1d_index(a, b):
    voida, voidb = map(asvoid, (a, b))
    return np.where(np.in1d(voidb, voida))[0]    

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

print(in1d_index(a, b))

印刷品

^{pr2}$

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

一些注意事项:

  1. 索引按递增顺序返回。它们不一致 到ba项的位置。在
  2. asvoid适用于整数数据类型,但使用asvoid时要小心 对于浮点数据类型,因为asvoid([-0.]) == asvoid([0.])返回 array([False])。在
  3. asvoid最适合于连续数组。如果数组不是连续的,数据将被复制到一个连续的数组中,这将降低性能。在

尽管有这些注意事项,但为了速度起见,还是可以选择使用in1d_index

^{3}$

因此in1d_indexin1d_index快了大约65倍(对于长度为低千分之一的数组),但是再次注意,这种比较并不完全是苹果对苹果,因为in1d_index以递增顺序返回索引,而{}返回{}在{中显示的顺序行中的索引。在

相关问题 更多 >