当搜索min
或max
值时,可以像这样获得找到的值的索引:
[val, index] = max(some_array_of_values);
如何获得median
价值指数?
注意:
是的,我知道中位数是什么,而且我知道它有时可以是中间两个值的平均值。我想要得到的是最接近或等于中值的值的索引。
值数组包含未排序的值。我们无法对该数组进行排序 - 我需要原始数组中的索引。但我们当然可以对它的副本进行排序。由于数组的大小没有限制 - 它相对较小(大约 100 个值)
这个想法是对向量进行排序,并取中间值。对于偶数长度的向量,我们计算中间两个值的平均值。
例子:
%# 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)
这是一个示例函数实现:
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
解决这个问题的一种方法是减去中位数并找到结果向量的绝对值的最小值:
[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));
对于包含中位数的集合,您可以使用查找和中位数。
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
后一种解决方案应该适用于这两种情况。请注意,不存在的中位数的索引根本不是正确的索引,您应该相应地使用该值(无论您想用它做什么)。
我想要得到的是最接近或等于中值的值的索引。值数组包含未排序的值。我们无法对这个数组进行排序。
您正在寻找一种快速选择算法。您很可能无法通过在 Matlab 本身中编写代码来击败内置的 Matlab 函数(如sort
和median
(据报道在内部使用))的性能,因为这将涉及慢循环。sort
相反,如果你真的需要比这些解决方案更高效的东西,你将不得不用编译语言实现你自己的。
nth_element
来自 Mathworks 文件交换的文件包括一个到 C++ 标准库函数的 mex 接口,std::nth_element
并包括一个特殊用途的fast_median
函数——这可能是一个很好的例子。您必须修改它以跟踪数组索引。
好的,我自己找到了一些解决方案。
首先,我对向量中的值进行排序D
S = sort(D)
然后我搜索大于或等于中位数的第一个元素
idS = find(S >= median(S),1)
现在我可以获得该元素的确切值并尝试在原始向量中找到它:
idMed = find(D == S(idS))
由于无法对数组进行排序(可能是因为它太大),并且因为问题不成立(如果数组中有奇数个元素该怎么办),只需执行以下操作:
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 个元素之一。