получить х элементов из центра вектора - PullRequest
0 голосов
/ 14 мая 2019

Как мне создать функцию (например, здесь, анонимную, но я не против) для получения x элементов из vec, которые наиболее центрированы (то есть вокруг медианы)? По сути, я хочу функцию с тем же синтаксисом, что и у Matlab randsample(n,k), но для неслучайных, с элементами, охватывающими центр.

cntr=@(vec,x) vec(round(end*.5)+(-floor(x/2):floor(x/2))); %this function in question
cntr(1:10,3) % outputs 3 values around median 5.5 => [4 5 6];
cntr(1:11,5) % outputs => [4 5 6 7 8]

Обратите внимание, что vec всегда сортируется.

Одна часть, с которой я борюсь, это не выводить больше, чем пределы vec. Например, cntr(1:10, 10) не должно выдавать ошибку.

edit: извините за ответы на многие обновления вопроса

Ответы [ 2 ]

3 голосов
/ 14 мая 2019

median требует сортировки элементов массива. Можно также отсортировать вручную и выделить средний блок ( редактировать: комментарий OP указывает, что элементы уже отсортированы, больше обоснования для простоты ):

function data = cntr(data,x)
x = min(x,numel(data)); % don't pick more elements than exist
data = sort(data);
start = floor((numel(data)-x)/2) + 1;
data = data(start:start+x-1);

Вы можете вставить это в однострочную анонимную функцию с некоторыми хитростями, но это только делает код уродливым. :)

Обратите внимание, что в случае неравномерного деления (когда мы не пропускаем четное количество элементов), здесь мы расставляем приоритеты для элемента слева. Вот что я имею в виду:

0 0 0 0 0 0 0 0 0 0 0   => 11 elements, x=4
      \_____/
picking these 4 values

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


Учитывая, что data (т.е. vec) уже отсортировано, операцию индексации можно сохранить в одной строке:

cntr = @(data,x) data( floor((numel(data)-x)/2) + (1:x) );

В этой строке отсутствует значение x = min(x,numel(data)), которое нам нужно добавить дважды, потому что мы не можем изменить переменную в анонимной функции:

cntr = @(data,x) data( floor((numel(data)-min(x,numel(data)))/2) + (1:min(x,numel(data))) );

Это мы можем упростить до:

cntr = @(data,x) data( floor(max(numel(data)-x,0)/2) + (1:min(x,numel(data))) );
3 голосов
/ 14 мая 2019

Это не однострочная анонимная функция, но вы можете сделать это довольно просто с помощью пары вызовов sort:

function vec = cntr(vec, x)
  [~, index] = sort(abs(vec-median(vec)));
  vec = vec(sort(index(1:min(x, end))));
end

Преимущество: она все равно вернетсятот же набор значений, даже если vec не отсортировано.Некоторые примеры:

>> cntr(1:10, 3)

ans =
     4     5     6

>> cntr(1:11, 5)

ans =
     4     5     6     7     8

>> cntr(1:10, 10)  % No indexing errors

ans =
     1     2     3     4     5     6     7     8     9    10

>> cntr([3 10 2 4 1 6 5 8 11 7 9], 5)  % Unsorted version of example 2

ans =

     4     6     5     8     7  % Same values, in their original order in vec


СТАРЫЙ ОТВЕТ

ПРИМЕЧАНИЕ. Это применимо к более ранней версии вопроса, где диапазон xзначения ниже и x значения выше медианы были желательны в качестве выходных данных.Оставляя это для потомков ...

Я разбил его на следующие этапы (начиная с отсортированного vec):

  1. Найти значения в vec меньшечем медиана, получите последние x индексы из них, затем возьмите первый (самый маленький) из них.Это начальный индекс.
  2. Найдите значения в vec больше медианы, получите первые из них x индексов, затем возьмите последний (самый большой) из них.Это конечный индекс.
  3. Используйте начальный и конечный индексы, чтобы выбрать центральную часть vec.

Вот реализация вышеприведенного с использованием функций find, min и max:

cntr = @(vec, x) vec(min(find(vec < median(vec), x, 'last')):max(find(vec > median(vec), x)));

И несколько тестов:

>> cntr(1:10, 3)  % 3 above and 3 below 5.5

ans =
     3     4     5     6     7     8

>> cntr(1:11, 5)  % 5 above and 5 below 6 (i.e. all of vec)

ans =
     1     2     3     4     5     6     7     8     9    10    11

>> cntr(1:10, 10)  % 10 above and 10 below 5.5 (i.e. all of vec, no indexing errors)

ans =
     1     2     3     4     5     6     7     8     9    10
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...