我如何创建一个函数(例如,这里是一个匿名函数,但我不介意任何一个)以从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)
不应引发错误。
编辑:很抱歉回答问题的人有很多更新
答案 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
开始):
vec
中找到小于中位数的值,获取这些索引的最后x
个索引,然后获取其中的第一个(最小的)索引。这是起始索引。vec
中的值,获取这些索引的第一个x
索引,然后获取它们的最后一个(最大)。这是结束索引。vec
的中心部分。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))) );