【问题标题】:How to compute frequency of rows in Matlab for submatrices?如何在 Matlab 中计算子矩阵的行频率?
【发布时间】:2014-10-01 23:06:53
【问题描述】:

我在 Matlab 中有一个矩阵 D。它是 4 个 3 行矩阵的串联(为清楚起见添加了中断)。我想确定总矩阵中唯一行的数量,并为每个子矩阵列出它们,并计算它们出现的次数。

D=[1 0 1 1; 
   0 1 1 1; 
   1 1 0 1; 
   --------
   1 1 0 1; 
   1 1 0 1; 
   0 1 1 1; 
   --------
   1 1 1 0; 
   0 1 1 1; 
   1 0 1 1;
   -------- 
   1 0 1 1; 
   1 0 1 1; 
   1 1 0 0]

所以对于上面的矩阵,有 5 个唯一行:

   1 0 1 1 
   0 1 1 1 
   1 1 0 1
   1 1 1 0 
   1 1 0 0 

因此,将这 5 行分成 4 个子矩阵,其中包含出现次数:

C=[1 0 1 1  1; 
   0 1 1 1  1; 
   1 1 0 1  1; 
   1 1 1 0  0; 
   1 1 0 0  0; 
   --------
   1 0 1 1  0; 
   0 1 1 1  1; 
   1 1 0 1  2; 
   1 1 1 0  0; 
   1 1 0 0  0; 
   ----------
   1 0 1 1  1; 
   0 1 1 1  1; 
   1 1 0 1  0; 
   1 1 1 0  1; 
   1 1 0 0  0; 
   ----------
   1 0 1 1  2; 
   0 1 1 1  0; 
   1 1 0 1  0; 
   1 1 1 0  0; 
   1 1 0 0  1]

【问题讨论】:

  • C的第一个子矩阵不应该是C=[1 0 1 1 2; 0 1 1 1 0; 1 1 0 1 1; 1 1 1 0 0; 1 1 0 0 0; ]吗?
  • 不,不应该是:C的第一个子矩阵看D的第一个nxk子矩阵。
  • 你在这个任务的哪一部分遇到了问题?
  • 在不循环的情况下获取 C 的最后一列
  • 为什么不循环播放?我认为这几乎是一个要求

标签: matlab matrix frequency


【解决方案1】:

代码

%// Cut into a 3D array after every n rows
mat3d = permute(reshape(D,n,size(D,1)/n,[]),[1 3 2])

%// Get unique rows
unqmat = unique(D,'rows','stable')

%// Find equalities
eqs = bsxfun(@eq,mat3d,permute(unqmat,[4 2 3 1]))

%// Get counts
counts = squeeze(sum(all(eqs,2),1)).' %//'

%// Restructure to get the desired output
C = [repmat(unqmat,[m 1]) counts(:)]

似乎较旧的 MATLAB 版本没有保持行顺序的 unique(..'rows','stable') 功能。同样,这是一个经过测试的建议替代品 -

function out = unique_rows_stable(A)

[unqmat_notinorder,row_ind] = unique(A,'rows');
[~,ordered_rowind] = sort(row_ind);
out = unqmat_notinorder(ordered_rowind,:);

return;

因此,可以将较早的解决方案代码编辑为具有unqmat = unique_rows_stable(D)

【讨论】:

  • 不确定“稳定”是什么意思。它在我的 Matlab 版本中不起作用
  • @CodeMonkey 你有什么版本的 MATLAB? stable 保持行顺序,仅此而已。
  • R2010a。做得很好。我不得不手动检查它,因为它没有保持订单:-P。我认为我的方法比必要的更暴力:-)
  • @CodeMonkey 是的,受益于新版本! :)
【解决方案2】:

如果D 只包含零和一:您可以将每一行解释为二进制数,然后使用accumarray 计算出现次数,如下所示:

nr = 3; %// number of rows of each submatrix
Db = bin2dec(char(D+'0'))+1; %// convert each row into a binary number, plus 1
R = accumarray([Db ceil(1/nr:1/nr:size(D,2)).'], 1, [], [], [], true); %'// count
%// occurrences. Sparse to save memory. Each col is a submatrix
[u v] = unique(Db,'stable'); %// unique values
R = reshape(R(u,:), [], 1); %// get only results for values that are present
C = [repmat(D(v,:), size(D,1)/nr, 1) full(R)]; %// build result

【讨论】:

    【解决方案3】:

    仅供参考,这样的问题通常会被关闭,因为它无法解释您尝试过的内容以及您实际遇到的问题。我只是觉得这听起来像是一个有趣的练习,而且我有一段时间没有用 Matlab 编写了,所以我想我会试一试。希望对您有所帮助!

    D=[1 0 1 1; 
       0 1 1 1; 
       1 1 0 1; 
       1 1 0 1; 
       1 1 0 1; 
       0 1 1 1; 
       1 1 1 0; 
       0 1 1 1; 
       1 0 1 1;
       1 0 1 1; 
       1 0 1 1; 
       1 1 0 0]
    
    rows = [];
    for i = 1:length(D)
        skip = 0;
        for j = 1:size(rows,1)
            if all(rows(j,:) == D(i,:))
                skip = 1;
            end
        end
        if ~skip
            rows = [rows; D(i,:)];
        end
    end
    C = [];
    for i = 1:4
        for j = 1:length(rows)
            count = 0;
            for k = 1:3
                if all(D((i-1)*3+k,:) == rows(j,:))
                    count = count + 1;
                end
            end
            C = [C; [rows(j,:) count]];
        end
    end
    
    C
    

    【讨论】:

    • 好吧,你让我为 rowsstable 的东西写了一个独特的函数。在我的解决方案中查看它,并随意使用它! :) +1 也是一个很好的替代解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多