我在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]
。
答案 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