获取关系为真的数组中的第一个索引

时间:2018-06-28 06:07:00

标签: python numpy

使用numpy,当ab > a具有不同的长度时,如何获取a中元素b的最后一个索引。

例如,对于以下值:

>>> a = np.asarray([10, 20, 30, 40])
>>> b = np.asarray([12, 25])

我期望结果为[0, 1](0 ..因为12 > 10-> a中的索引0; 1 ..因为25 > 20-> { {1}})。显然,结果向量的长度应等于a的长度(并且结果列表的值应小于b的长度(因为它们引用{{1}中的索引}))。

另一项测试是针对a(与上述a相同),结果应为b = np.asarray([12, 25, 31, 9, 99])

4 个答案:

答案 0 :(得分:3)

矢量化解决方案:

请记住,您可以使用广播将b中的所有元素与a中的所有元素进行比较:

b[:, None] > a
# array([[ True, False, False, False],     # b[0] > a[:]
#        [ True,  True, False, False]])    # b[1] > a[:]

现在找到每行中最后一个True值的索引,该值等于每行中第一个False值的负1

np.argmin((b[:, None] > a), axis=1) - 1
# array([0, 1])

请注意,返回值-1的含义可能不明确。可能是

  1. b[x]a中的所有元素,或者
  2. b[x] 不大于a
  3. 中的任何元素

在我们的数据中,这意味着

a = np.asarray([10, 20, 30, 40])
b = np.asarray([9, 12, 25, 39, 40, 41, 50])

mask = b[:, None] > a
# array([[False, False, False, False],   # 9 is smaller than a[:], case 2
#        [ True, False, False, False],
#        [ True, False, False, False],
#        [ True,  True,  True, False],
#        [ True,  True,  True, False],
#        [ True,  True,  True,  True],   # 41 is larger than a[:], case 1
#        [ True,  True,  True,  True]])  # 50 is larger than a[:], case 1

因此,对于情况1,我们需要找到具有所有True值的行:

is_max = np.all(mask, axis=1)

对于情况2,我们需要找到具有所有False值的行:

none_found = np.all(~mask, axis=1)

这意味着我们可以使用is_max查找并用正索引替换所有案例1 -1的值

mask = b[:, None] > a
is_max = np.all(mask, axis=1)
# array([False, False, False, False, False,  True,  True])
idx = np.argmin(mask, axis=1) - 1
# array([-1,  0,  0,  2,  2, -1, -1])
idx[is_max] = len(a) - 1
# array([-1,  0,  0,  2,  2,  3,  3])

但是请注意,索引-1具有含义:就像3一样,它已经意味着“最后一个元素”。因此,如果要使用idx进行索引,将-1保留为无效值标记可能会造成麻烦。

答案 1 :(得分:0)

np.asarray([i for i in range(len(b)) if b[i]>a[i]])

这应该给您答案。长度也不必与a或b相同。

答案 2 :(得分:0)

即使a的长度比b的长度短,也可以先选择较短的列表长度,然后检查其元素编号是否较小:

[i for i in range(min(len(a),len(b))) if min(a, b, key=len)[i] > max(a, b, key=len)[i]]
# [0, 1]

答案 3 :(得分:0)

您可以zip a和b进行组合,然后enumerate对其索引进行迭代

[i for i,(x,y) in enumerate(zip(a,b)) if y>x]
# [0, 1]