Получить первый индекс в массиве, где отношение истинно - PullRequest
0 голосов
/ 28 июня 2018

Как я могу получить последний индекс элемента в a, где b > a, когда a и b имеют различную длину, используя numpy.

Например, для следующих значений:

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

Я бы ожидал результата [0, 1] (0 .. потому что 12 > 10 -> index 0 в a; 1 .. потому что 25 > 20 -> index 1 в a). Очевидно, что длина результирующего вектора должна равняться длине b (а значения списка результатов должны быть меньше длины a (поскольку они относятся к индексам в a)).

Еще один тест для b = np.asarray([12, 25, 31, 9, 99]) (такой же a, как указано выше), результат должен быть array([ 0, 1, 2, -1, 3]).

Ответы [ 4 ]

0 голосов
/ 28 июня 2018

Векторизованное решение:

Помните, что вы можете сравнить все элементы в 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

В наших данных это означает

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 в качестве маркера недопустимого значения может вызвать проблемы в будущем.

0 голосов
/ 28 июня 2018

Работает даже 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]
0 голосов
/ 28 июня 2018

Вы можете zip a и b объединить их, а затем enumerate, чтобы повторить его с индексом

[i for i,(x,y) in enumerate(zip(a,b)) if y>x]
# [0, 1]
0 голосов
/ 28 июня 2018
np.asarray([i for i in range(len(b)) if b[i]>a[i]])

Это должно дать вам ответ. Также длина не должна быть такой же, как у a или b.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...