Python 对于2d numpy数组的每一行,获取第二个2d数组中相等行的索引

Python 对于2d numpy数组的每一行,获取第二个2d数组中相等行的索引,python,arrays,numpy,Python,Arrays,Numpy,我有两个巨大的2d numpy整数数组X和U,其中U被假定只有unqiue行。对于X中的每一行,我希望获得U中匹配行的对应行索引(如果有,否则为-1)。例如,如果以下数组作为输入传递: U = array([[1, 4], [2, 5], [3, 6]]) X = array([[1, 4], [3, 6], [7, 8], [1, 4]]) 输出应为: array([0,2,-1,0]) 有没有一种有效的方法可以用Nu

我有两个巨大的2d numpy整数数组X和U,其中U被假定只有unqiue行。对于X中的每一行,我希望获得U中匹配行的对应行索引(如果有,否则为-1)。例如,如果以下数组作为输入传递:

U = array([[1, 4],
       [2, 5],
       [3, 6]])

X = array([[1, 4],
       [3, 6],
       [7, 8],
       [1, 4]])
输出应为:

array([0,2,-1,0])
有没有一种有效的方法可以用Numpy实现这一点(或类似的方法)

@迪瓦卡: 你的方法对我来说失败了

print(type(rows), rows.dtype, rows.shape)
print(rows[:10])
print(search2D_indices(rows[:10], rows[:10]))

<class 'numpy.ndarray'> int32 (47398019, 5)
[[65536     1     1     1    17]
 [65536     1     1     1   153]
 [65536     1     1     2   137]
 [65536     1     1     3   153]
 [65536     1     1     9   124]
 [65536     1     1    13   377]
 [65536     1     1    13   134]
 [65536     1     1    13   137]
 [65536     1     1    13   153]
 [65536     1     1    13   439]]
[ 0  1  2  3  4 -1 -1 -1 -1  9]
print(类型(行)、rows.dtype、rows.shape)
打印(行[:10])
打印(搜索2D_索引(行[:10],行[:10]))
int32(47398019,5)
[[65536     1     1     1    17]
[65536     1     1     1   153]
[65536     1     1     2   137]
[65536     1     1     3   153]
[65536     1     1     9   124]
[65536     1     1    13   377]
[65536     1     1    13   134]
[65536     1     1    13   137]
[65536     1     1    13   153]
[65536     1     1    13   439]]
[ 0  1  2  3  4 -1 -1 -1 -1  9]

这是一种基于词典的方法:

import numpy as np

U = np.array([[1, 4],
              [2, 5],
              [3, 6]])

X = np.array([[1, 4],
              [3, 6],
              [7, 8],
              [1, 1]])

d = {v: k for k, v in enumerate(map(tuple, U))}

res = np.array([d.get(tuple(a), -1) for a in X])

# [ 0  2 -1 -1]
方法#1

受to的启发,这里是一个使用-

样本运行-

In [121]: U
Out[121]: 
array([[1, 4],
       [2, 5],
       [3, 6]])

In [122]: X
Out[122]: 
array([[1, 4],
       [3, 6],
       [7, 8],
       [1, 4]])

In [123]: search2D_indices(U, X, fillval=-1)
Out[123]: array([ 0,  2, -1,  0])
In [142]: U
Out[142]: 
array([[-1, -4],
       [ 2,  5],
       [ 3,  6]])

In [143]: X
Out[143]: 
array([[-1, -4],
       [ 3,  6],
       [ 7,  8],
       [-1, -4]])

In [144]: search2D_indices_v2(U, X, fillval=-1)
Out[144]: array([ 0,  2, -1,  0])

方法#2

扩展到具有负整数的情况,我们需要偏移
dims
,并相应地转换为
1D
,如下所示-

def search2D_indices_v2(X, searched_values, fillval=-1):
    X_lim = X.max()-X.min(0)
    searched_values_lim = searched_values.max()-searched_values.min(0)

    dims = np.maximum(X_lim, searched_values_lim)+1
    s = dims.cumprod()

    X1D = X.dot(s)
    searched_valuesID = searched_values.dot(s)
    sidx = X1D.argsort()
    idx = np.searchsorted(X1D,searched_valuesID,sorter=sidx)
    idx[idx==len(sidx)] = 0    
    idx_out = sidx[idx]

    return np.where(X1D[idx_out] == searched_valuesID, idx_out, fillval)
样本运行-

In [121]: U
Out[121]: 
array([[1, 4],
       [2, 5],
       [3, 6]])

In [122]: X
Out[122]: 
array([[1, 4],
       [3, 6],
       [7, 8],
       [1, 4]])

In [123]: search2D_indices(U, X, fillval=-1)
Out[123]: array([ 0,  2, -1,  0])
In [142]: U
Out[142]: 
array([[-1, -4],
       [ 2,  5],
       [ 3,  6]])

In [143]: X
Out[143]: 
array([[-1, -4],
       [ 3,  6],
       [ 7,  8],
       [-1, -4]])

In [144]: search2D_indices_v2(U, X, fillval=-1)
Out[144]: array([ 0,  2, -1,  0])
方法#3

另一个基于
视图
-

# https://stackoverflow.com/a/45313353/ @Divakar
def view1D(a, b): # a, b are arrays
    a = np.ascontiguousarray(a)
    b = np.ascontiguousarray(b)
    void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
    return a.view(void_dt).ravel(),  b.view(void_dt).ravel()

def search2D_indices_views(X, searched_values, fillval=-1):
    X1D,searched_valuesID = view1D(X, searched_values)
    sidx = X1D.argsort()
    idx = np.searchsorted(X1D,searched_valuesID,sorter=sidx)
    idx[idx==len(sidx)] = 0    
    idx_out = sidx[idx]
    return np.where(X1D[idx_out] == searched_valuesID, idx_out, fillval)
您可以使用广播以矢量化的方式确定项目的公平性。之后,您可以简单地使用
all
函数 在一个适当的轴上得到期望的真值,对应于预期的指数。最后,使用
np.where
得到股票价格指数 发生,只需将其重新分配给先前创建的填充有-1的数组

In [47]: result = np.full(X.shape[0], -1)

In [48]: x, y = np.where((X[:,None] == U).all(-1))

In [49]: result[x] = y

In [50]: result
Out[50]: array([ 0,  2, -1,  0])
请注意,正如文档中也提到的,关于宽泛型铸造,您应该注意:

虽然这在代码行方面非常有效,但在计算上可能有效,也可能无效。问题是在算法的中间步骤中计算的三维差分阵列。对于小型数据集,在阵列上创建和操作可能非常快。然而,大型数据集将生成计算效率低下的大型中间数组


我想这将是一种减缓的方式,因为for循环。X和U有大约10^7-10^8的争吵,为什么投反对票?这个答案有什么问题我可以改进吗?仅仅因为表现不是最好的并不能成为否决的理由。关键是最好的答案是通过投票上升到最高点+1.@Kasramvd不是我,同意jpp@jpp这个解决方案是完全矢量化的,但肯定不是最好的/实际上没有什么是最好的lol。但不管怎样,这违反了SO的向下投票规则。只有当答案错误或与给定问题无关时,才应投反对票。@miradulo确实如此,但这不是重点。你是对的,你可以随意投反对票,这是一个明显的事实,你可以,但这并不意味着你应该。另一点是,这个解决方案比其他基于Numpy的方法(无意冒犯tho)更直截了当、更容易理解,并且回答问题非常正确,但不是以极快的方式。这段代码有很多优点,其中一个可以通过矢量化的方式解决问题,加上广播的优点和缺点。这种方法对我来说失败了,请看我的编辑question@user2224350是的,的确是一只虫子。应该在刚才的编辑中修复。嗯,我仍然得到相同的错误。然而,第三种方法是有效的。这真的很快!非常感谢@user2224350,这可能是溢出的情况。尝试将输入转换为
np.int64
dtype。