Я пытаюсь понять функцию argpartition numpy. Я сделал пример документация как можно более простым.
import numpy as np
x = np.array([3, 4, 2, 1])
print("x: ", x)
a=np.argpartition(x, 3)
print("a: ", a)
print("x[a]:", x[a])
Это результат ...
('x: ', array([3, 4, 2, 1]))
('a: ', array([2, 3, 0, 1]))
('x[a]:', array([2, 1, 3, 4]))
В строке a = np.argpartition (x, 3) не является ли k-й элемент последним элементом (числом 1)? Если это число 1, то при сортировке x не должен ли 1 стать первым элементом (элементом 0)?
В x [a], почему 2 является первым элементом "впереди" 1?
Что фундаментального мне не хватает?
@PaulPanzer: Преимущество наивного partition по сравнению с concatenate состоит в том, что он может работать за один проход.






Я помню, что мне тоже было трудно понять это, возможно, документация написана плохо, но это то, что это значит
Когда вы выполняете a=np.argpartition(x, 3), тогда x сортируется таким образом, что будет отсортирован только элемент с k-м индексом (в нашем случае k = 3)
Поэтому, когда вы запускаете этот код, в основном вы спрашиваете, какое значение будет у третьего индекса в отсортированном массиве. Следовательно, на выходе будет ('x[a]:', array([2, 1, 3, 4])), где сортируется только элемент 3.
Поскольку документ предполагает, что все числа, меньшие, чем k-й элемент, находятся перед ним (в произвольном порядке), вы получаете 2 перед 1, поскольку в нем нет определенного порядка.
Надеюсь, это проясняет ситуацию, если вы все еще в замешательстве, не стесняйтесь комментировать :)
Спасибо. Части, в которых говорится: «x отсортирован таким образом, что будет отсортирован только элемент в позиции 3», действительно помогли. Спасибо. PS. Я закончил тем, что отметил выше как правильный ответ, потому что у него был хороший пример кода, и мы можем выбрать только один ответ.
Более полный ответ на то, что делает argpartition, находится в документации перегородка, и в нем говорится:
Creates a copy of the array with its elements rearranged in such a way that the value of the element in k-th position is in the position it would be in a sorted array. All elements smaller than the k-th element are moved before this element and all equal or greater are moved behind it. The ordering of the elements in the two partitions is undefined.
Итак, для входного массива 3, 4, 2, 1 отсортированный массив будет 1, 2, 3, 4.
Результат np.partition([3, 4, 2, 1], 3) будет иметь правильное значение (то есть такое же, как у отсортированного массива) в третьем (то есть последнем) элементе. Правильное значение для 3-го элемента - 4.
Позвольте мне показать это для всех значений k, чтобы было понятно:
np.partition([3, 4, 2, 1], 0) - [1, 4, 2, 3]np.partition([3, 4, 2, 1], 1) - [1, 2, 4, 3]np.partition([3, 4, 2, 1], 2) - [1, 2, 3, 4]np.partition([3, 4, 2, 1], 3) - [2, 1, 3, 4]Другими словами: k-й элемент результата совпадает с k-м элементом отсортированного массива. Все элементы до k меньше или равны этому элементу. Все элементы после него больше или равны ему.
То же самое происходит с argpartition, за исключением того, что argpartition возвращает индексы, которые затем можно использовать для получения того же результата.
Как и @Imtinan, я боролся с этим. Я счел полезным разбить функцию на arg и раздел.
Возьмем следующий массив:
array = np.array([9, 2, 7, 4, 6, 3, 8, 1, 5])
the corresponding indices are: [0,1,2,3,4,5,6,7,8] where 8th index = 5 and 0th = 9
если мы сделаем np.partition(array, k=5), код возьмет 5-й элемент (не индекс), а затем поместит его в новый массив. Затем он поместит эти элементы <5-го элемента перед ним и этого> 5-го элемента после, например:
pseudo output: [lower value elements, 5th element, higher value elements]
если мы вычислим это, мы получим:
array([3, 5, 1, 4, 2, 6, 8, 7, 9])
Это имеет смысл, поскольку 5-й элемент в исходном массиве = 6, [1,2,3,4,5] все меньше 6, а [7,8,9] больше 6. Обратите внимание, что элементы не упорядочены .
Затем часть arg np.argpartition() делает еще один шаг и меняет местами элементы на их соответствующие индексы в исходном массиве. Итак, если бы мы сделали:
np.argpartition(array, 5) получим:
array([5, 8, 7, 3, 1, 4, 6, 2, 0])
сверху исходный массив имел такую структуру [index = value] [0 = 9, 1 = 2, 2 = 7, 3 = 4, 4 = 6, 5 = 3, 6 = 8, 7 = 1, 8 = 5]
вы можете сопоставить значение индекса с выходом, и вы удовлетворяете условию:
argpartition() = partition(), вот так:
[форма индекса] массив ([5, 8, 7, 3, 1, 4, 6, 2, 0]) становится
[3, 5, 1, 4, 2, 6, 8, 7, 9]
который совпадает с выводом np.partition(array),
array([3, 5, 1, 4, 2, 6, 8, 7, 9])
Надеюсь, это имеет смысл, это был единственный способ разобраться в части функции arg.
partition/argpartitionразбивается на k-й элемент по порядку, а не по позиции. Последнее не потребует специального алгоритма, потому что вы можете просто сделать что-то вродеnp.concatenate([x[x<x[3]], x[x ==x[3]], x[[x>x[3]]). Умный момент вpartition- это поиск k-го элемента без выполнения полной сортировки.