Получение индекса медианного значения в MATLAB - PullRequest
1 голос
/ 08 августа 2011

При поиске значения min или max можно получить индекс найденного значения следующим образом:

[val, index] = max(some_array_of_values);

Как получить индекс значения median?

ПРИМЕЧАНИЕ:
Да, я знаю, что такое медиана, и знаю, что иногда она может быть средней из двух значений в середине.Я хочу получить индекс значения, ближайшего или равного срединному значению.
Массив значений содержит несортированные значения.Мы не можем отсортировать этот массив - мне нужен индекс из исходного массива.Но, конечно, мы можем отсортировать его копию.Нет ограничений из-за размера массива - он относительно мал (около 100 значений)

Ответы [ 6 ]

3 голосов
/ 04 февраля 2014

Один из способов решения этой проблемы - вычесть медиану и найти минимум абсолютных значений результирующего вектора:

[val, index] = min(abs(some_array_of_values - median(some_array_of_values)));

В результате вы получите наиболее близкое значение к медиане.

Это должно работать для нахождения любого индекса значения, ближайшего к value_of_interest.

[val, index] = min(abs(some_array_of_values - value_of_interest));
3 голосов
/ 08 августа 2011

Идея состоит в том, чтобы отсортировать вектор и взять среднее значение. Для векторов четной длины мы вычисляем среднее значение двух значений в середине.

Пример:

%# some random vector
%#x = rand(99,1);        %# odd-length
x = rand(100,1);         %# even-length

%# index/indices for median value
num = numel(x);
[~,ord] = sort(x);
idx = ord(floor(num/2)+(rem(num,2)==0):floor(num/2)+1);

%# median value
med = mean( x(idx) );

%# compare against MATLAB's function
median(x)

EDIT

Вот пример реализации функции:

function [med idx] = mymedian(x)
    %# MYMEDIAN
    %#
    %# Input:   x        vector
    %# Output:  med      median value
    %# Output:  idx      corresponding index
    %#
    %# Note: If vector has even length, idx contains two indices
    %# (their average is the median value)
    %#
    %# Example:
    %#    x = rand(100,1);
    %#    [med idx] = mymedian(x)
    %#    median(x)
    %#
    %# Example:
    %#    x = rand(99,1);
    %#    [med idx] = mymedian(x)
    %#    median(x)
    %#
    %# See also: median
    %#

    assert(isvector(x));
    [~,ord] = sort(x);
    num = numel(x);

    if rem(num,2)==0
        %# even
        idx = ord(floor(num/2):floor(num/2)+1);
        med = mean( x(idx) );
    else
        %# odd
        idx = ord(floor(num/2)+1);
        med = x(idx);
    end
end
3 голосов
/ 08 августа 2011

Для наборов, которые включают медиану, вы можете использовать поиск и медиану.

 a = [1, 2, 3, 4, 5]
 find(a == median(a))

Для наборов, которые не включают их медиану, вы должны стать умными. Сначала мы находим наименьший индекс, который больше медианы, и наибольший индекс, который меньше медианы. Здесь, конечно, я предполагаю, что набор отсортирован. Это делает все проще.

 b = [1, 2, 3, 4]
 (min(find(b>median(b))) + max(find(b<median(b)))) / 2

Последнее решение должно работать в обоих случаях. Обратите внимание, что индекс для несуществующей медианы совсем не является правильным индексом, и вы должны использовать значение соответствующим образом (для всего, что вы, возможно, захотите с ним сделать).

0 голосов
/ 08 августа 2011

То, что я хочу получить, это индекс значения, ближайшего или равного срединному значению.Массив значений содержит несортированные значения.Мы не можем отсортировать этот массив.

Вы ищете быстрый алгоритм выбора .Скорее всего, вы не сможете превзойти производительность встроенных функций Matlab, таких как sort и median (которые, как сообщается, будут использовать sort для внутреннего использования), написав код в самом Matlab, поскольку это будет включать медленные циклы,Вместо этого, если вам действительно нужно что-то более эффективное, чем эти решения, вам придется реализовать свое собственное на скомпилированном языке.

nth_element из обмена файлами Mathworks включает в себя интерфейс mex длястандартная библиотечная функция C ++ std::nth_element и включает специальную функцию fast_median - это может быть хорошим примером для начала.Вам придется изменить это, чтобы отслеживать индикаторы массива.

0 голосов
/ 08 августа 2011

Поскольку массив не может быть отсортирован (предположительно потому, что он очень большой) и потому что вопрос некорректен (что делать в случае нечетного числа элементов в массиве), просто выполните следующее:

ixMedian = function(v)

if (mod(numel(v),2) == 1)
   vtemp = v(1:end-1);
else
   vtemp = v;
end

ixMedian = find(vtemp == median(vtemp))

В случае нечетного числа элементов возвращается медиана.В случае четного числа элементов возвращается один из 4 элементов, ближайших к медиане.Если элементы распределены равномерно, и если их 2N, то с вероятностью 1 / N возвращается один из 2 элементов, ближайших к медиане.

0 голосов
/ 08 августа 2011

ОК, я нашел какое-то решение самостоятельно.

Сначала я сортирую значения в моем векторе D

S = sort(D)

Затем я ищу первый элемент, который больше чемили равно медиане

idS = find(S >= median(S),1)

Теперь я могу получить точное значение этого элемента и попытаться найти его в исходном векторе:

idMed = find(D == S(idS))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...