Понимание numpy.where
Я хочу получить первый индекс элемента массива numpy, который больше, чем какой-либо конкретный элемент того же массива. Я пробовал следующее:
>>> Q5=[[1,2,3],[4,5,6]]
>>> Q5 = np.array(Q5)
>>> Q5[0][Q5>Q5[0,0]]
array([2, 3])
>>> np.where(Q5[0]>Q5[0,0])
(array([1, 2], dtype=int32),)
>>> np.where(Q5[0]>Q5[0,0])[0][0]
1
Q1. Правильный ли выше способ получить первый индекс элемента Q5[0]больше, чем Q5[0,0]?
Меня больше беспокоит np.where(Q5[0]>Q5[0,0])возвращение кортежа (array([1, 2], dtype=int32),)и, следовательно, мне нужно удвоить индекс [0][0]в конце np.where(Q5[0]>Q5[0,0])[0][0].
Q2. Почему этот возвращаемый кортеж, но ниже возвращает правильный массив numpy?
>>> np.where(Q5[0]>Q5[0,0],Q5[0],-1)
array([-1, 2, 3])
Чтобы я мог напрямую индексировать:
>>> np.where(Q5[0]>Q5[0,0],Q5[0],-1)[1]
2
Ответы
In [58]: A = np.arange(1,10).reshape(3,3)
In [59]: A.shape
Out[59]: (3, 3)
In [60]: A
Out[60]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
np.whereс просто состоянием действительно np.nonzero.
Создайте логический массив:
In [63]: A==6
Out[63]:
array([[False, False, False],
[False, False, True],
[False, False, False]])
Найдите, где это правда:
In [64]: np.nonzero(A==6)
Out[64]: (array([1]), array([2]))
Результатом является кортеж, по одному элементу на измерение условия. Каждый элемент представляет собой индексирующий массив, вместе они определяют расположение True (s)
Еще один тест с несколькими True
In [65]: (A%3)==1
Out[65]:
array([[ True, False, False],
[ True, False, False],
[ True, False, False]])
In [66]: np.nonzero((A%3)==1)
Out[66]: (array([0, 1, 2]), array([0, 0, 0]))
Использование кортежа для индексации исходного массива:
In [67]: A[np.nonzero((A%3)==1)]
Out[67]: array([1, 4, 7])
Использование аргумента 3 whereдля создания нового массива со смесью значений из AиA+10
In [68]: np.where((A%3)==1,A+10, A)
Out[68]:
array([[11, 2, 3],
[14, 5, 6],
[17, 8, 9]])
Если условие имеет несколько значений True, nonzeroэто не тестовый инструмент для поиска «первого», поскольку он обязательно находит все.
Ненулевой кортеж можно превратить в 2d-массив с помощью transpose. На самом деле может быть проще получить «первое» из этого массива:
In [73]: np.argwhere((A%3)==1)
Out[73]:
array([[0, 0],
[1, 0],
[2, 0]])
Вы смотрите в 1d-массиве, строку A:
In [77]: A[0]>A[0,0]
Out[77]: array([False, True, True])
In [78]: np.nonzero(A[0]>A[0,0])
Out[78]: (array([1, 2]),) # 1 element tuple
In [79]: np.argwhere(A[0]>A[0,0])
Out[79]:
array([[1],
[2]])
In [81]: np.where(A[0]>A[0,0], 100, 0) # 3 argument where
Out[81]: array([ 0, 100, 100])
Итак, ищите ли вы массив 1d или 2d (или 3 или 4), nonzeroвозвращает кортеж с одним элементом массива для каждого измерения. Таким образом, его всегда можно использовать для индексации массива аналогичного размера. Кортеж 1d может выглядеть избыточным, но он согласуется с результатами других измерений.
Пытаясь понять подобные операции, внимательно прочтите документацию и просмотрите отдельные шаги. Здесь я рассмотрю условную матрицу, nonzeroрезультат и различные способы ее использования.
numpy.where () похож на цикл for с if.
numpy.where(condition, values, new_value)
condition - как если бы условия.
values - значения для итерации по
new_value - если условие истинно для значения , оно изменится на new_value
Если мы хотим записать его для одномерного массива, он должен выглядеть примерно так:
[xv if c else yv
for c, xv, yv in zip(condition, x, y)]
Пример:
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.where(a < 5, a, 10*a)
array([ 0, 1, 2, 3, 4, 50, 60, 70, 80, 90])
Сначала мы создаем массив с числами от 0 до 9 (0, 1, 2 ... 7, 8, 9),
а затем проверяем все значения в массиве, которые больше 5, и умножаем их значение на 10.
Итак, теперь все значения в массиве, которые меньше 5, остались прежними, а все значения, которые больше, умножены на 10
Использование argmaxс логическим массивом даст вам индекс первого True.
In [54]: q
Out[54]:
array([[1, 2, 3],
[4, 5, 6]])
In [55]: q > q[0,0]
Out[55]:
array([[False, True, True],
[ True, True, True]], dtype=bool)
argmax может принимать аргумент оси / размера.
In [56]: np.argmax(q > q[0,0], 0)
Out[56]: array([1, 0, 0], dtype=int64)
Это говорит о том, что первое значение True является индексом один для нулевого столбца и нулевым индексом для столбцов один и два.
In [57]: np.argmax(q > q[0,0], 1)
Out[57]: array([1, 0], dtype=int64)
Это говорит о том, что первое значение True является индексом один для нулевой строки и нулевым индексом для первой строки.
Q1. Правильный ли выше способ получить первый индекс элемента в Q5 [0] больше Q5 [0,0]?
Нет , я хотел бы использовать argmaxс 1для axisаргумента затем выберите первый пункт из этого результата.
Q2. Почему этот возвращаемый кортеж
Вы сказали ему возвращать -1значения False и возвращать Q5[0]элементы для значений True.
Q2 ... но ниже возвращается правильный массив numpy?
Вам повезло, и вы выбрали правильный индекс.