计算满载向量的单元格中的唯一行

时间:2014-09-26 18:08:57

标签: matlab cell-array

我在MATLAB中有一个单元格,其中每个元素包含一个不同长度的向量

e.g。

C = {[1 2 3], [2 4 5 6], [1 2 3], [6 4], [7 6 4 3], [4 6], [6 4]}

如您所见,某些向量会重复,其他向量则是唯一的。

我想计算每个向量发生的次数并返回计数,以便我可以在GUI中填充表,其中每行是唯一的组合,日期显示每个组合出现的次数。

e.g。

            Count
"[1 2 3]"     2
"[6 4]"       2
"[2 4 5 6]"   1
"[7 6 4 3]"   1
"[4 6]"       1

我应该说每个向量中数字的顺序很重要,即[6 4]与[4 6]不一样。

有什么想法,我怎么能相当有效地做到这一点?

感谢迄今为止评论过的人。正如@Divakar所指出的那样,我忘了提到矢量中的值可以超过一位数。即[46, 36 28]。我的原始代码会将向量[1 2 3 4]连接到1234,然后使用hist进行计数。当然,当你达到一位数以上时会出现这种情况,因为你可以区分[1, 2, 3, 4][12, 34]

3 个答案:

答案 0 :(得分:6)

您可以将所有条目转换为char,然后转换为2D数字数组,最后使用unique(...'rows')获取唯一行的标签,并使用它们来计算它们的数量。

C = {[46, 36 28], [2 4 5 6], [46, 36 28], [6 4], [7 6 4 3], [4 6], [6 4]} %// Input

char_array1 = char(C{:})-0; %// convert input cell array to a char array
[~,unqlabels,entry_labels] = unique(char_array1,'rows'); %// get unique rows
count = histc(entry_labels,1:max(entry_labels)); %// counts of each unique row

为了以问题中提出的格式显示输出,您可以使用 -

out = [C(unqlabels)' num2cell(count)];

输出 -

out = 
    [1x4 double]    [1]
    [1x2 double]    [1]
    [1x2 double]    [2]
    [1x4 double]    [1]
    [1x3 double]    [2]

并显示celldisp -

的唯一行
ans{1} =
     2     4     5     6
ans{2} =
     4     6
ans{3} =
     6     4
ans{4} =
     7     6     4     3
ans{5} =
    46    36    28

编辑:如果你有负数,你需要做更多的工作来设置char_array1,如下所示,其余的代码保持不变 -

lens = cellfun(@numel,C);
mat1(max(lens),numel(lens))=0;
mat1(bsxfun(@ge,lens,[1:max(lens)]')) = horzcat(C{:});
char_array1 = mat1';

答案 1 :(得分:3)

我能想到的一种方法是转换为字符串,然后使用unique

Cs = cellfun(@(x)(mat2str(x)),C,'uniformoutput',false);
[Cu,idx_u,idx] = unique(Cs);

现在您可以使用idx计算出现次数,例如使用

fv=tabulate(idx)

所以fv已经提供了您需要的所有信息,但出于显示目的,我将添加:

[Cu' , num2cell(fv(:,2))]

ans = 

'[1 2 3]'      [2]
'[2 4 5 6]'    [1]
'[4 6]'        [1]
'[6 4]'        [2]
'[7 6 4 3]'    [1]

答案 2 :(得分:3)

我能想到的另一个建议是将每个数组转换为数字串联,然后执行直方图来计算每个条目有多少个值。我们需要弄清楚我们首先拥有多少个唯一数字,它们将作为unique的直方图边缘。

我需要注意的一件事是,我们假设每个单元格中数组中的每个元素都是单个数字。如果有两位数或更多的数字,这显然不会起作用。

换句话说:

%// Convert each array of numbers into a single number
numbers = cellfun(@(x) sum(x.*10.^(numel(x)-1:-1:0)), C);
%// Find unique numbers
uniNumbers = unique(numbers);

%// Get histogram
out = histc(numbers, uniNumbers);

%// Display counts
disp([uniNumbers; out]);

out将包含cell数组中每个唯一编号的计数。我们得到:

      46          64         123        2456        7643
       1           2           2           1           1

第一行代码的技巧是我使用基数10中的数字分解,其中每个数字可以唯一地表示为10的幂的倍数之和。因此,4587可以表示为:

4000 + 500 + 80 + 7 ==> 4*10^3 + 5*10^2 + 8*10^1 + 7*10^0

我在数组中取了每个数字,并将它们用作每个递减幂10的系数,然后将它们全部加在一起。因此,在您的单元格数组[1 2 3]中,转换为123,依此类推。在您的示例中,这是numbers的输出,正在执行我上面谈到的内容:

numbers =

  Columns 1 through 6

         123        2456         123          64        7643          46

  Column 7

          64

将其与C中的实际单元格数组进行比较:

celldisp(C)

C{1} = 
     1     2     3     
C{2} =
     2     4     5     6
C{3} =
     1     2     3 
C{4} =
     6     4
C{5} =
     7     6     4     3
C{6} =
     4     6
C{7} =
     6     4