从向量中心获取x元素

时间:2019-05-14 19:45:39

标签: arrays matlab vector

我如何创建一个函数(例如,这里是一个匿名函数,但我不介意任何一个)以从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)不应引发错误。

编辑:很抱歉回答问题的人有很多更新

2 个答案:

答案 0 :(得分:3)

这不是单行匿名函数,但是您可以通过几次调用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的中心部分。

以下是使用功能findminmax的上述实现:

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

答案 1 :(得分:3)

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))) );