在python numpy中找到特定值之前的最后一个元素的位置

时间:2016-03-26 03:42:00

标签: python numpy

我有这个人。 python numpy array,arr:

([1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 3L, 3L, 3L, 2L, 2L, 2L,
       2L, 2L, 2L, 1L, 1L, 1L, 1L])

我可以找到第一次出现的1:

np.where(arr.squeeze() == 1)[0]

如何在0或3之前找到最后1的位置。

2 个答案:

答案 0 :(得分:1)

您可以使用rolling window并搜索您想要的值:

import numpy as np
arr = np.array([1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 3L, 3L, 3L, 2L, 2L, 2L,
       2L, 2L, 2L, 1L, 1L, 1L, 1L])

def rolling_window(a, window):
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window)
    strides = a.strides + (a.strides[-1],)
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides)

match_1_0 = np.all(rolling_window(arr, 2) == [1, 0], axis=1)
match_1_3 = np.all(rolling_window(arr, 2) == [1, 3], axis=1)
all_matches = np.logical_or(match_1_0, match_1_3)
print(np.flatnonzero(all_matches)[-1])

根据您的阵列,这可能在性能方面足够好。话虽如此,一个不太灵活(但更简单)的解决方案可能表现得更好,即使它是你通常希望避免使用numpy的索引循环...:< / p>

for ix in xrange(len(arr) - 2, -1, -1):  # range in python3.x
    if arr[ix] == 1 and (arr[ix + 1] == 0 or arr[ix + 1] == 3):
        return ix

您甚至可以做一些比上面的硬编码解决方案更灵活的事情(我猜)仍然可能超出滚动窗口解决方案:

def rfind(haystack, needle):
    len_needle = len(needle)
    for ix in xrange(len(haystack) - len_needle, -1, -1):  # range in python3.x
        if (haystack[ix:ix + len_needle] == needle).all():
            return ix

在这里,您可以执行以下操作:

max(rfind(arr, np.array([1, 0])), rfind(arr, np.array([1, 3])))

当然,有了所有这些答案,我还没有真正处理过你所搜索的东西不存在的情况,因为你没有说明你想要的东西。情况下...

答案 1 :(得分:1)

这是使用np.wherenp.in1d -

的一种方法
# Get the indices of places with 0s or 3s and this 
# decides the last index where we need to look for 1s later on
last_idx = np.where(np.in1d(arr,[0,3]))[0][-1]

# Get all indices of 1s within the range of last_idx and choose the last one
out = np.where(arr[:last_idx]==1)[0][-1]

请注意,对于未找到索引的情况,使用[0][-1]之类的内容会抱怨没有元素,因此需要将错误检查代码包裹在这些行中。

示例运行 -

In [118]: arr
Out[118]: array([1, 1, 3, 0, 3, 2, 0, 1, 2, 1, 0, 2, 2, 3, 2])

In [119]: last_idx = np.where(np.in1d(arr,[0,3]))[0][-1]

In [120]: np.where(arr[:last_idx]==1)[0][-1]
Out[120]: 9