如何在不使用MATLAB循环的情况下找到矢量中最常见的元素?

时间:2016-10-07 18:35:18

标签: matlab loops for-loop vectorization

对于第一个最常见的元素,我们使用mode。要找到i最常见的元素,我不知道除了继续删除第一个最常见的元素,第二个最常见的元素,......之外的任何其他更好的方法,直到{{1来自数据集的最常见元素:

i-1

使用矢量化而不是循环可以有更好更快的方法吗?

3 个答案:

答案 0 :(得分:4)

您可以将accumarraysortunique一起使用,以生成数据数组中唯一值的bin计数。

例如:

function [val, count] = getnthmost(x, n)
% Get unique values in x (uniquevals) and their location (ic)
[uniquevals, ~, ic] = unique(x);

% Accumulate the indices and sort in descending order
[bincounts_sorted, idx] = sort(accumarray(ic, 1), 'descend');

% Get the nthmost value and its count
val = uniquevals(idx(n));
count = bincounts_sorted(n);
end

一个小例子:

x = randi(5, 10, 1);
[val, count] = getnthmost(x, 2);

返回:

x =

     2     5     1     2     2     1     3     4     3     4


val =

     1


count =

     2

请注意sort按照它们在排序数组中出现的顺序处理'tie',而不考虑排序方向,因此如果我们有[1, 2, 3, 2],我们的升序排序索引将是[1, 2, 4, 3]并且降序排序索引为[3, 2, 4, 1]

操作实例

我们在这里使用unique来查找输入数组x中的所有唯一值。我们还存储可选的第三个输出,它是x的值到唯一值数组中的索引的映射。然后,我们可以使用accumarray使用我们从1获得的下标来累积unique的元素。换句话说,我们得到每个索引的计数。我们按降序对此计数进行排序并存储输出索引,以便我们可以将计数映射回我们的唯一值数组中的值。然后我们可以使用n来选择并返回适当的值和计数。

答案 1 :(得分:2)

假设我们有一个包含此值的数据集:

data = [5 5 4 2 5 8 8 5 8 4 ];

为了找到最常见的项目,您注意到mode是最好的方法。 但为了找到最常见的项目,我们研究histogram数据,显示每个元素重复的数量。 在Matlab中,hist函数用于计算直方图。 hist的第一个参数是数据,第二个参数是元素的唯一值,所以在这个例子中它们是[2 4 5 8]

元素的unqiue值

unique_val = unique(data);
2 4 5 8

直方图计算

[count val] = hist(data, unique_val);

绘制直方图,您可以这样使用hist

hist(data, unique_val);

所以我们有这样一个数字:

      _
      _  _
   _  _  _
_  _  _  _ 
2  4  5  8

从视觉上我们发现5是第一个最常见的项目,8是第二个最常见的项目....

但是要以数字方式找到该项目,我们可以按降序对直方图进行排序,以获得这样的数字:

_
_  _
_  _  _  
_  _  _  _
5  8  4  2

所以5是第8个是第2个......

在Matlab中,我们将count和val连接为freq

freq =  [count; val].';

然后根据第一列count计算freq。 (减号用于降序排序,1用于第一列):

out = sortrows(freq , -1)

然后out(i,2)是第i个最常用的项目。 简而言之,所有解释的内容都会导致这一点:

%find count of data
[count val] = hist(data(:,1),unique(data(:,1)));
freq = [count; val].';
%sort counts descendingly
out = sortrows(freq,-1);

现在out(i,2)是最常见的元素

答案 2 :(得分:2)

这是一种方式:

x = [2 2 3 1 5 1 1 3 3 3 4 1 2 5 4 3 1 3 3 4]; % data
ii = 2; % find tthe second most frequent value
sx = sort(x); % sort x
ind = [true diff(sx)~=0]; % logical index of each new value in the sorted vector
counts = diff(find([ind true])); % count of each unique value
vals = sx(ind); % unique values
[~, is] = sort(counts, 'descend'); % counts in decreasing order
result = vals(is(ii)); % value with the ii-th largest count

在此示例中,

>> vals
vals =
     1     2     3     4     5
>> counts
counts =
     5     3     7     3     2
>> result
result =
     1