如何在Matlab中按列计数模式?

时间:2015-02-10 03:16:44

标签: matlab matrix frequency

我在Matlab中有一个矩阵S,如下所示:

2   2   1   2
2   3   1   1
3   3   1   1
3   4   1   1
3   1   2   1
4   1   3   1
1   1   3   1

我想按列计算值的模式。我对任何列中编号3后后面的数字的频率感兴趣。例如,数字3在第一列中出现三次。我们第一次观察它时,接着是3次,第二次接着是3次,第三次接着是4.因此,在第一列中观察到的图案的频率看起来像是:

3-3: 66.66%
3-4: 33.33% 
3-1: 0%
3-2: 0%

5 个答案:

答案 0 :(得分:2)

这是一种方法,找到3'然后查看以下数字

[i,j]=find(S==3);
k=i+1<=size(S,1);
T=S(sub2ind(size(S),i(k)+1,j(k))) %// the elements of S that are just below a 3
R=arrayfun(@(x) sum(T==x)./sum(k),1:max(S(:))).' %// get the number of probability of each digit

答案 1 :(得分:2)

我将以我能理解的方式重述您的问题陈述,我的解决方案将反映这一新的问题陈述。

  1. 对于特定列,请找到包含数字3的位置。
  2. 查看这些位置正下方的行,并查看这些位置的值
  3. 获取这些值并计算找到的总发生次数。
  4. 对所有列重复这些操作并更新计数器,然后确定值的出现百分比。
  5. 我们可以通过以下方式做到这一点:

    A = [2   2   1   2
    2   3   1   1
    3   3   1   1
    3   4   1   1
    3   1   2   1
    4   1   3   1
    1   1   3   1]; %// Define your matrix
    [row,col] = find(A(1:end-1,:) == 3);
    vals = A(sub2ind(size(A), row+1, col));
    h = 100*accumarray(vals, 1) / numel(vals)
    
    h =
    
              0
              0
        66.6667
        33.3333
    

    让我们慢慢浏览上面的代码。前几行定义了您的示例矩阵A。接下来,我们会查看矩阵的所有行除了最后一行,并查看数字3与find的位置。我们跳过最后一行,因为我们希望确保我们在矩阵的范围内。如果在最后一行有一个数字3,如果我们试图检查最后一行以下的值,我们会有未定义的行为,因为那里什么都没有!

    一旦我们这样做,我们就会看一下矩阵中那些数字为3的那些值。我们使用sub2ind来帮助我们实现这一点。接下来,我们使用这些值并使用accumarray计算它们,然后将它们的总和归一化为百分比。

    结果将是一个4元素数组,显示每个数字遇到的百分比。

    要仔细检查,如果我们查看矩阵,我们会看到3的值跟随其他值3,总共4次 - 第一列,第3行,第4行,第二列,第2行和第3列,第6行。值4遵循3的值两次:第一列,第6行,第二列,第3行。

    总共,我们计算了6个数字,因此除以6得到数字3和2/6的4/6或66.67%或数字4的33.33%。

答案 2 :(得分:2)

要生成输出,您可以使用方便的tabulate

S = [
    2   2   1   2
    2   3   1   1
    3   3   1   1
    3   4   1   1
    3   1   2   1
    4   1   3   1
    1   1   3   1];

idx = find(S(1:end-1,:)==3);
S2 = S(2:end,:);

tabulate(S2(idx))
  Value    Count   Percent
      1        0      0.00%
      2        0      0.00%
      3        4     66.67%
      4        2     33.33%

答案 3 :(得分:1)

如果我正确地得到了问题陈述,你可以用MATLAB's logical indexing和一种基本上两行的方法有效地实现这个 -

%// Input 2D matrix
S = [
    2   2   1   2
    2   3   1   1
    3   3   1   1
    3   4   1   1
    3   1   2   1
    4   1   3   1
    1   1   3   1]

Labels = [1:4]'; %//'# Label array

counts = histc(S([false(1,size(S,2)) ; S(1:end-1,:) == 3]),Labels)
Percentages = 100*counts./sum(counts)

验证/显示结果

下面列出的用于显示输出结果的样式使用MATLAB's table来获取人类可读的数据格式。

风格#1

>> table(Labels,Percentages)
ans = 
    Labels    Percentages
    ______    ___________
    1              0     
    2              0     
    3         66.667     
    4         33.333     

风格#2

你可以做一些奇特的字符串操作,以更“代表性”的方式呈现结果 -

>> Labels_3 = strcat('3-',cellstr(num2str(Labels','%1d')'));
>> table(Labels_3,Percentages)
ans = 
    Labels_3    Percentages
    ________    ___________
    '3-1'            0     
    '3-2'            0     
    '3-3'       66.667     
    '3-4'       33.333    

样式#3

如果您想根据问题的预期输出部分中列出的百分比以降序排列方式显示它们,您可以使用sort -

执行其他步骤
>> [Percentages,idx] = sort(Percentages,'descend');
>> Labels_3 = strcat('3-',cellstr(num2str(Labels(idx)','%1d')'));
>> table(Labels_3,Percentages)
ans = 
    Labels_3    Percentages
    ________    ___________
    '3-3'       66.667     
    '3-4'       33.333     
    '3-1'            0     
    '3-2'            0   

奖励资料:查找所有情况的频率(计数)

现在,让我们假设你想重复这个过程来说124,即在12之后找到匹配项和4分别。在这种情况下,您可以针对所有情况迭代上述步骤,同样可以使用arrayfun -

%// Get counts
C = cell2mat(arrayfun(@(n) histc(S([false(1,size(S,2)) ; S(1:end-1,:) == n]),...
    1:4),1:4,'Uni',0))

%// Get percentages
Percentages = 100*bsxfun(@rdivide, C, sum(C,1))

给我们 -

Percentages =
   90.9091   20.0000         0  100.0000
    9.0909   20.0000         0         0
         0   60.0000   66.6667         0
         0         0   33.3333         0

因此,在Percentages中,第一列是在输入矩阵中某处[1,2,3,4]之后发生的1计数。举个例子,当在输入矩阵中column -3之后查找元素时,可以看到Percentages 3是示例输出中的{{1}}。

答案 4 :(得分:1)

如果您想为每列独立计算的频率

S = [2   2   1   2
     2   3   1   1
     3   3   1   1
     3   4   1   1
     3   1   2   1
     4   1   3   1
     1   1   3   1];                                    %// data: matrix
N = 3;                                                  %// data: number
r = max(S(:));
[R, C] = size(S);
[ii, jj] = find(S(1:end-1,:)==N);                       %// step 1
count = full(sparse(S(ii+1+(jj-1)*R), jj, 1, r, C));    %// step 2
result = bsxfun(@rdivide, count, sum(S(1:end-1,:)==N)); %// step 3

其工作原理如下:

    首先应用
  1. find来确定NS除了最后一行之外的count次出现的行和列索引。
  2. 在变量S中为每列累积条目正下方步骤1的索引中的值。非常方便的sparse函数用于此目的。请注意,这会将linear indexing用于count
  3. 要获取每列的频率,N除以每列中result = 0 0 0 NaN 0 0 0 NaN 0.6667 0.5000 1.0000 NaN 0.3333 0.5000 0 NaN 的出现次数(bsxfun)。
  4. 此示例中的结果是

    NaN

    请注意,最后一列正确包含{{1}} s,因为该列的搜索模式的频率未定义。