python函数返回一个数组_python - 是否有一个NumPy函数返回数组中某个东西的第一个索引?...

python - 是否有一个NumPy函数返回数组中某个东西的第一个索引?

我知道Python列表有一种方法可以返回第一个索引:

>>> l = list([1, 2, 3])

>>> l.index(2)

1

NumPy阵列有类似的东西吗?

13个解决方案

412 votes

是的,这是给出NumPy数组array和值item的答案,用于搜索:

itemindex = numpy.where(array==item)

结果是一个元组,首先是所有行索引,然后是所有列索引。

例如,如果一个数组是两个维度,那么它在两个位置包含您的项目

array[itemindex[0][0]][itemindex[1][0]]

将等于你的项目,所以会

array[itemindex[0][1]][itemindex[1][1]]

numpy.where

Alex answered 2019-01-28T01:29:24Z

60 votes

如果您需要第一次出现的索引只有一个值,您可以使用t(或where,在这种情况下相同的事情):

>>> t = array([1, 1, 1, 2, 2, 3, 8, 3, 8, 8])

>>> nonzero(t == 8)

(array([6, 8, 9]),)

>>> nonzero(t == 8)[0][0]

6

如果您需要多个值中的每个值的第一个索引,您显然可以重复执行与上面相同的操作,但有一个技巧可能更快。 以下查找每个子序列的第一个元素的索引:

>>> nonzero(r_[1, diff(t)[:-1]])

(array([0, 3, 5, 6, 7, 8]),)

请注意,它找到3s的子序列的开始和8s的两个子序列:

[1,1,1,2,2,3,8,3,8,8]

所以它与找到每个值的第一次出现略有不同。 在您的程序中,您可以使用排序版本t来获得您想要的内容:

>>> st = sorted(t)

>>> nonzero(r_[1, diff(st)[:-1]])

(array([0, 3, 5, 7]),)

Vebjorn Ljosa answered 2019-01-28T01:30:13Z

33 votes

您还可以将NumPy数组转换为空中列表并获取其索引。 例如,

l = [1,2,3,4,5] # Python list

a = numpy.array(l) # NumPy array

i = a.tolist().index(2) # i will return index of 2

print i

它将打印1。

Hima answered 2019-01-28T01:30:41Z

14 votes

如果您打算将其用作其他内容的索引,则可以使用布尔索引(如果数组是可广播的); 你不需要明确的指数。 绝对最简单的方法是简单地根据真值进行索引。

other_array[first_array == item]

任何布尔操作都有效:

a = numpy.arange(100)

other_array[first_array > 50]

非零方法也采用布尔值:

index = numpy.nonzero(first_array == item)[0][0]

两个零用于索引的元组(假设first_array是1D),然后是索引数组中的第一个项。

Matt answered 2019-01-28T01:31:23Z

9 votes

只是为了找到第一个索引,添加一个非常高性能和方便的numba替代方案,基于np.argwhere:

from numba import njit

import numpy as np

@njit

def index(array, item):

for idx, val in np.ndenumerate(array):

if val == item:

return idx

# If no item was found return None, other return types might be a problem due to

# numbas type inference.

这非常快,并且可以自然地处理多维数组:

>>> arr1 = np.ones((100, 100, 100))

>>> arr1[2, 2, 2] = 2

>>> index(arr1, 2)

(2, 2, 2)

>>> arr2 = np.ones(20)

>>> arr2[5] = 2

>>> index(arr2, 2)

(5,)

与使用np.argwhere或np.nonzero的任何方法相比,这可以更快(因为它使操作短路)。

但是,np.argwhere也可以优雅地处理多维数组(您需要手动将其转换为元组并且它不会被短路)但如果找不到匹配则会失败:

>>> tuple(np.argwhere(arr1 == 2)[0])

(2, 2, 2)

>>> tuple(np.argwhere(arr2 == 2)[0])

(5,)

MSeifert answered 2019-01-28T01:32:06Z

6 votes

要对任何条件进行索引,您可以执行以下操作:

In [1]: from numpy import *

In [2]: x = arange(125).reshape((5,5,5))

In [3]: y = indices(x.shape)

In [4]: locs = y[:,x >= 120] # put whatever you want in place of x >= 120

In [5]: pts = hsplit(locs, len(locs[0]))

In [6]: for pt in pts:

.....: print(', '.join(str(p[0]) for p in pt))

4, 4, 0

4, 4, 1

4, 4, 2

4, 4, 3

4, 4, 4

这里有一个快速的函数来执行list.index()所做的事情,但如果没有找到则不会引发异常。 注意 - 这在大型阵列上可能非常慢。 如果你更愿意将它作为一种方法使用,你可以将其修补到数组上。

def ndindex(ndarray, item):

if len(ndarray.shape) == 1:

try:

return [ndarray.tolist().index(item)]

except:

pass

else:

for i, subarray in enumerate(ndarray):

try:

return [i] + ndindex(subarray, item)

except:

pass

In [1]: ndindex(x, 103)

Out[1]: [4, 0, 3]

Autoplectic answered 2019-01-28T01:32:34Z

6 votes

%timeit返回最小的i,使得i是列表中第一次出现x的索引。

可以安全地假设Python中的%timeit函数已经实现,以便在找到第一个匹配项后停止,这样可以获得最佳的平均性能。

要查找在NumPy数组中第一次匹配后停止的元素,请使用迭代器(ndenumerate)。

In [67]: l=range(100)

In [68]: l.index(2)

Out[68]: 2

NumPy数组:

In [69]: a = np.arange(100)

In [70]: next((idx for idx, val in np.ndenumerate(a) if val==2))

Out[70]: (2L,)

请注意,如果未找到该元素,则两种方法%timeit和where都会返回错误。 使用nonzero,可以使用第二个参数来返回特殊值,以防未找到该元素,例如

In [77]: next((idx for idx, val in np.ndenumerate(a) if val==400),None)

NumPy中还有其他功能(%timeit,where和nonzero)可用于查找数组中的元素,但它们都有缺点,即遍历整个数组查找所有出现的内容,因此未针对查找所有实例进行优化。 第一要素。 另请注意,where和nonzero返回数组,因此您需要选择第一个元素来获取索引。

In [71]: np.argmax(a==2)

Out[71]: 2

In [72]: np.where(a==2)

Out[72]: (array([2], dtype=int64),)

In [73]: np.nonzero(a==2)

Out[73]: (array([2], dtype=int64),)

时间比较

只检查大型数组,当搜索项位于数组的开头时,使用迭代器的解决方案更快(在IPython shell中使用%timeit):

In [285]: a = np.arange(100000)

In [286]: %timeit next((idx for idx, val in np.ndenumerate(a) if val==0))

100000 loops, best of 3: 17.6 µs per loop

In [287]: %timeit np.argmax(a==0)

1000 loops, best of 3: 254 µs per loop

In [288]: %timeit np.where(a==0)[0][0]

1000 loops, best of 3: 314 µs per loop

这是一个开放的NumPy GitHub问题。

另见:Numpy:快速找到第一个价值指数

user2314737 answered 2019-01-28T01:33:57Z

4 votes

对于1D阵列,我推荐np.flatnonzero(array == value)[0],它相当于np.nonzero(array == value)[0][0]和np.where(array == value)[0][0],但避免了取消装箱1元素元组的丑陋。

1'' answered 2019-01-28T01:34:19Z

4 votes

NumPy中有很多操作可能可以组合在一起来实现这一目标。 这将返回等于item的元素索引:

numpy.nonzero(array - item)

然后,您可以使用列表的第一个元素来获取单个元素。

Ned Batchelder answered 2019-01-28T01:34:47Z

3 votes

对于一维排序数组,使用numpy.searchsorted返回NumPy整数(位置)会更加简单和有效O(log(n))。 例如,

arr = np.array([1, 1, 1, 2, 3, 3, 4])

i = np.searchsorted(arr, 3)

只需确保数组已经排序

还检查返回的索引i是否实际包含搜索的元素,因为searchsorted的主要目标是查找应插入元素以维持顺序的索引。

if arr[i] == 3:

print("present")

else:

print("not present")

Alok Nayak answered 2019-01-28T01:35:23Z

2 votes

从np.where()中选择第一个元素的另一种方法是使用生成器表达式和枚举,例如:

>>> import numpy as np

>>> x = np.arange(100) # x = array([0, 1, 2, 3, ... 99])

>>> next(i for i, x_i in enumerate(x) if x_i == 2)

2

对于二维数组,可以这样做:

>>> x = np.arange(100).reshape(10,10) # x = array([[0, 1, 2,... 9], [10,..19],])

>>> next((i,j) for i, x_i in enumerate(x)

... for j, x_ij in enumerate(x_i) if x_ij == 2)

(0, 2)

这种方法的优点是它在找到第一个匹配后停止检查数组的元素,而np.where检查所有元素是否匹配。 如果数组中的早期匹配,则生成器表达式会更快。

Noyer282 answered 2019-01-28T01:35:58Z

1 votes

numpy_indexed包(免责声明,我是它的作者)包含numpy.ndarray的矢量化等效list.index; 那是:

sequence_of_arrays = [[0, 1], [1, 2], [-5, 0]]

arrays_to_query = [[-5, 0], [1, 0]]

import numpy_indexed as npi

idx = npi.indices(sequence_of_arrays, arrays_to_query, missing=-1)

print(idx) # [2, -1]

该解决方案具有矢量化性能,推广到ndarray,并具有处理缺失值的各种方法。

Eelco Hoogendoorn answered 2019-01-28T01:36:26Z

-1 votes

注意:这是针对python 2.7版本的

您可以使用lambda函数来处理问题,它可以在NumPy数组和列表上运行。

your_list = [11, 22, 23, 44, 55]

result = filter(lambda x:your_list[x]>30, range(len(your_list)))

#result: [3, 4]

import numpy as np

your_numpy_array = np.array([11, 22, 23, 44, 55])

result = filter(lambda x:your_numpy_array [x]>30, range(len(your_list)))

#result: [3, 4]

你可以使用

result[0]

获取过滤元素的第一个索引。

对于python 3.6,请使用

list(result)

代替

result

Statham answered 2019-01-28T01:37:15Z

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值