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