Oct*_*lus 14 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]])
对于这个例子,我想要一个结果,如:
[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)
我找到了类似问题的答案,但它仅适用于1d阵列.
有没有办法以更简单的方式做我想做的事情?
Div*_*kar 22
方法#1
一种方法是使用NumPy broadcasting,像这样 -
np.where((X==searched_values[:,None]).all(-1))[1]
方法#2
一种内存有效的方法是将每一行转换为线性索引等价物,然后使用np.in1d,如下所示 -
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]
方法#3
使用np.searchsorted和使用相同的转换为线性索引等价的哲学的另一种内存有效方法就像这样 -
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方法假定存在一个匹配,从各行searched_values在X.
np.ravel_multi_index工作怎么样?此函数为我们提供线性索引等效数字.它接受一个2D数组n-dimensional indices,设置为列和n维网格本身的形状,在这些网格上将映射这些索引,并计算等效线性索引.
让我们使用我们对手头问题的输入.以输入为例X,记下第一行.因为,我们试图将每一行转换X为它的线性索引等价,并且因为np.ravel_multi_index假设每列作为一个索引元组,我们需要X在进入函数之前进行转置.因为,X在这种情况下每行的元素数量是2,要映射到的n维网格将是2D.每行有3个元素X,它将是3D用于映射的网格等等.
要了解此函数如何计算线性指数,请考虑第一行X-
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_multi_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_multi_index并验证那些线性指数 -
In [84]: np.ravel_multi_index(X.T,dims)
Out[84]: array([30, 66, 61, 24, 41])
因此,我们将具有对应于每个索引元组的线性索引X,即来自每个索引元组X.
选择尺寸np.ravel_multi_index以形成独特的线性指数
现在,将每行X作为n维网格的索引元组并将每个这样的元组转换为标量的思想背后的想法是具有对应于唯一元组的唯一标量,即唯一的行X.
让我们再看看X-
In [77]: X
Out[77]: 
array([[4, 2],
       [9, 3],
       [8, 5],
       [3, 3],
       [5, 6]])
现在,正如上一节所讨论的,我们将每一行都视为索引元组.在每个这样的索引元组内,第一个元素将表示n-dim网格的第一个轴,第二个元素将是网格的第二个轴,依此类推,直到每行的最后一个元素为止X.实质上,每列代表网格的一个维度或轴.如果我们要将所有元素映射X到相同的n-dim网格上,我们需要考虑这种建议的n-dim网格的每个轴的最大拉伸.假设我们正在处理正数X,那么这样的延伸将是X+ 1 中每列的最大值.这+ 1是因为Python遵循0-based索引.因此,例如,X[1,0] == 9将映射到建议网格的第10行.同样,X[4,1] == 6将转到7th该网格的列.
所以,对于我们的样本案例,我们有 -
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.
另一种方法是使用asvoid(下面)view每行作为dtype 的单个 
值void.这将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]
该numpy_indexed包(免责声明:我是它的作者)包含的功能用于有效地执行这样的操作(也使用引擎盖下searchsorted)。在功能方面,它相当于 list.index 的矢量化等价物:
import numpy_indexed as npi
result = npi.indices(X, searched_values)
请注意,使用 'missing' kwarg,您可以完全控制丢失项目的行为,它也适用于 nd-arrays(fi;图像堆栈)。
更新:使用与@RikX=[520000,28,28]和相同的形状searched_values=[20000,28,28],它在 中运行0.8064 secs,使用 missing=-1 来检测和表示 X 中不存在的条目。
| 归档时间: | 
 | 
| 查看次数: | 6702 次 | 
| 最近记录: |