Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.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数组中多个值的行索引_Python_Arrays_Numpy - Fatal编程技术网

Python 查找numpy数组中多个值的行索引

Python 查找numpy数组中多个值的行索引,python,arrays,numpy,Python,Arrays,Numpy,我有一个数组X: X = np.array([[4, 2], [9, 3], [8, 5], [3, 3], [5, 6]]) 我希望找到这个数组中多个值行的索引: searched_values = np.array([[4, 2], [3, 3], [5, 6

我有一个数组X:

X = np.array([[4,  2],
              [9,  3],
              [8,  5],
              [3,  3],
              [5,  6]])
我希望找到这个数组中多个值行的索引:

searched_values = np.array([[4, 2],
                            [3, 3],
                            [5, 6]])
对于本例,我希望得到如下结果:

[0,3,4]
我有一个这样做的代码,但我认为它太复杂了:

X = np.array([[4,  2],
              [9,  3],
              [8,  5],
              [3,  3],
              [5,  6]])

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

result = []

for s in searched_values:
    idx = np.argwhere([np.all((X-s)==0, axis=1)])[0][1]
    result.append(idx)

print(result)
我发现了一个类似的问题,但它只适用于一维数组

有没有一种更简单的方法来做我想做的事情?

方法#1

一种方法是像这样使用-

np.where((X==searched_values[:,None]).all(-1))[1]
dims = X.max(0)+1
out = np.where(np.in1d(np.ravel_multi_index(X.T,dims),\
                    np.ravel_multi_index(searched_values.T,dims)))[0]
dims = X.max(0)+1
X1D = np.ravel_multi_index(X.T,dims)
searched_valuesID = np.ravel_multi_index(searched_values.T,dims)
sidx = X1D.argsort()
out = sidx[np.searchsorted(X1D,searched_valuesID,sorter=sidx)]
方法#2

一种节省内存的方法是将每一行转换为等价的线性索引,然后像这样使用-

np.where((X==searched_values[:,None]).all(-1))[1]
dims = X.max(0)+1
out = np.where(np.in1d(np.ravel_multi_index(X.T,dims),\
                    np.ravel_multi_index(searched_values.T,dims)))[0]
dims = X.max(0)+1
X1D = np.ravel_multi_index(X.T,dims)
searched_valuesID = np.ravel_multi_index(searched_values.T,dims)
sidx = X1D.argsort()
out = sidx[np.searchsorted(X1D,searched_valuesID,sorter=sidx)]
方法#3

另一种高效内存的方法是使用相同的转换为线性索引等价物的原理-

np.where((X==searched_values[:,None]).all(-1))[1]
dims = X.max(0)+1
out = np.where(np.in1d(np.ravel_multi_index(X.T,dims),\
                    np.ravel_multi_index(searched_values.T,dims)))[0]
dims = X.max(0)+1
X1D = np.ravel_multi_index(X.T,dims)
searched_valuesID = np.ravel_multi_index(searched_values.T,dims)
sidx = X1D.argsort()
out = sidx[np.searchsorted(X1D,searched_valuesID,sorter=sidx)]
请注意,此
np.searchsorted
方法假定
X
中的
searched\u值中的每一行都有匹配项


它是如何工作的? 此函数为我们提供了线性索引等价数。它接受一个
2D
数组,设置为列和n维网格本身的形状,这些索引将映射到该网格上,并计算等效的线性索引

让我们利用手头问题的输入。以输入
X
为例,记下它的第一行。因为,我们试图将
X
的每一行转换为它的线性索引等价物,并且因为
np.ravel\u multi\u index
假设每一列都是一个索引元组,所以在输入函数之前,我们需要对
X
进行转置。由于在这种情况下,
X
中每行元素的数量是
2
,因此要映射到的n维网格将是
2D
。在
X
中,每行有3个元素,它应该是
3D
网格,用于映射等等

查看此函数如何计算线性索引,考虑<代码> x < /代码> -< /p>的第一行。

In [77]: X
Out[77]: 
array([[4, 2],
       [9, 3],
       [8, 5],
       [3, 3],
       [5, 6]])
In [77]: X
Out[77]: 
array([[4, 2],
       [9, 3],
       [8, 5],
       [3, 3],
       [5, 6]])
我们将n维网格的形状设置为
dims
-

In [78]: dims
Out[78]: array([10,  7])
让我们创建二维网格,看看映射是如何工作的,并使用
np.ravel\u multi\u index
-

In [79]: out = np.zeros(dims,dtype=int)

In [80]: out
Out[80]: 
array([[0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0]])
让我们设置
X
中的第一个索引元组,即
X
中的第一行-

In [81]: out[4,2] = 1

In [82]: out
Out[82]: 
array([[0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0]])
现在,为了查看刚刚设置的元素的线性索引等价物,让我们展平并使用
np.where
来检测
1

In [83]: np.where(out.ravel())[0]
Out[83]: array([30])
如果考虑到行主顺序,也可以计算此值

让我们使用
np.ravel\u multi\u index
并验证这些线性索引-

In [84]: np.ravel_multi_index(X.T,dims)
Out[84]: array([30, 66, 61, 24, 41])
因此,我们将具有与
X
中的每个索引元组对应的线性索引,即
X
中的每一行

np.ravel\u多重索引选择维度
以形成唯一的线性索引

现在,将
X
的每一行视为一个n维网格的索引元组,并将每一个这样的元组转换为一个标量,其背后的思想是具有对应于唯一元组的唯一标量,即
X
中的唯一行

让我们再看一看
X
-

In [77]: X
Out[77]: 
array([[4, 2],
       [9, 3],
       [8, 5],
       [3, 3],
       [5, 6]])
In [77]: X
Out[77]: 
array([[4, 2],
       [9, 3],
       [8, 5],
       [3, 3],
       [5, 6]])
现在,如前一节所讨论的,我们将每一行视为索引元组。在每个这样的索引元组中,第一个元素表示n-dim网格的第一个轴,第二个元素表示网格的第二个轴,依此类推,直到
X
中每行的最后一个元素。本质上,每一列将代表网格的一个维度或轴。如果我们要把所有的元素从<代码> x>代码>映射到同一个n-朦胧网格上,我们需要考虑这样一个提出的n-朦胧网格的每个轴的最大拉伸。假设我们处理的是
X
中的正数,那么这样的延伸就是
X
+1中每列的最大值。
+1
是因为Python遵循基于
0的
索引。因此,例如
X[1,0]==9
将映射到建议网格的第10行。类似地,
X[4,1]==6将进入该网格的
7列

因此,对于我们的示例案例,我们有-

In [7]: dims = X.max(axis=0) + 1 # Or simply X.max(0) + 1

In [8]: dims
Out[8]: array([10,  7])
因此,对于我们的示例案例,我们需要一个形状至少为
(10,7)
的网格。沿维度增加长度不会有什么坏处,也会给我们带来唯一的线性指数

结束语:这里需要注意的一件重要事情是,如果在
X
中有负数,我们需要沿
X
中的每列添加适当的偏移量,以使这些索引元组成为正数,然后再使用
np.ravel_multi_index

X = np.array([[4,  2],
              [9,  3],
              [8,  5],
              [3,  3],
              [5,  6]])

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

result = [[i for i,row in enumerate(X) if (s==row).all()] for s in S]


如果您想要一个简单的列表(假设每个搜索值正好有一个匹配)。

另一种选择是使用
asvoid
(以下)将每一行作为单个行查看
void
dtype的值。这将2D数组缩减为1D数组,从而允许您像往常一样使用
np.in1d

import numpy as np

def asvoid(arr):
    """
    Based on http://stackoverflow.com/a/16973510/190597 (Jaime, 2013-06)
    View the array as dtype np.void (bytes). The items along the last axis are
    viewed as one value. This allows comparisons to be performed which treat
    entire rows as one value.
    """
    arr = np.ascontiguousarray(arr)
    if np.issubdtype(arr.dtype, np.floating):
        """ Care needs to be taken here since
        np.array([-0.]).view(np.void) != np.array([0.]).view(np.void)
        Adding 0. converts -0. to 0.
        """
        arr += 0.
    return arr.view(np.dtype((np.void, arr.dtype.itemsize * arr.shape[-1])))

X = np.array([[4,  2],
              [9,  3],
              [8,  5],
              [3,  3],
              [5,  6]])

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

idx = np.flatnonzero(np.in1d(asvoid(X), asvoid(searched_values)))
print(idx)
# [0 3 4]
该软件包(免责声明:我是其作者)包含有效执行此类操作的功能(还使用引擎盖下的searchsorted)。就功能而言,它相当于list.index的矢量化等价物:

import numpy_indexed as npi
result = npi.indices(X, searched_values)
请注意,使用“missing”kwarg,您可以完全控制丢失项的行为,并且它也适用于nd数组(fi;图像堆栈)


更新:使用与@Rik
X=[520000,28,28]
searched\u values=[20000,28,28]
相同的形状,它运行时间为
0.8064秒
,使用missing=-1来检测和表示X中不存在的条目。

这里有一个非常快速的解决方案,可以使用numpy和hashlib进行良好的扩展。它可以在几秒钟内处理大尺寸矩阵或图像。我在520000 X(28 X 28)阵列和20000 X(28 X 28)阵列上使用它,在我的CPU上只需2秒钟

代码:

输出:

unique_idx= [4 3 0]
X[unique_idx]= [[5 6]
 [3 3]
 [4 2]]

另一种方法是使用
scipy.space.distance