简体   繁体   English

如何在Matlab中为子矩阵计算行频?

[英]How to compute frequency of rows in Matlab for submatrices?

I have a matrix D in Matlab. 我在Matlab中有一个矩阵D It is a concatenation of 4 matrices of 3 rows (breaks added for clarity). 它是3行的4个矩阵的串联(为清楚起见添加了中断)。 I would like to determine the number of unique rows within the total matrix and list them out for each of the sub-matrices with a count of how many times they occur. 我想确定总矩阵中唯一行的数量,并为每个子矩阵列出它们,并计算它们出现多少次。

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]

So for the above matrix, there are 5 unique rows: 因此,对于上述矩阵,有5个唯一的行:

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

So breaking those 5 rows into the 4 sub-matrices with counts of occurrence within them it would be: 因此,将这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]

Code

%// 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(:)]

Seems like older MATLAB versions don't have unique(..'rows','stable') capability that keeps the row order. 似乎较旧的MATLAB版本没有保持行顺序的unique(..'rows','stable')功能。 For the same, here is a suggested replacement that is tested as well - 出于相同的原因,这也是经过测试的建议替代品-

function out = unique_rows_stable(A)

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

return;

Thus, the earlier solution code could be edited to have unqmat = unique_rows_stable(D) instead. 因此,可以将早期的解决方案代码编辑为具有unqmat = unique_rows_stable(D)

If D only contains zeros and ones: you can interpret each row as a binary number and then use accumarray to count ocurrences, as follows: 如果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

FYI, a question like this would normally be shut down since it doesn't explain what you've tried and what you're actually struggling with. 仅供参考,像这样的问题通常会被关闭,因为它不能解释您尝试过的内容以及您实际上正在努力解决的问题。 I just thought it sounded like a fun exercise and I haven't written in Matlab for a while so I thought I'd give it a go. 我只是认为这听起来像是一个有趣的练习,而且我有一段时间没用Matlab编写过,所以我认为我可以尝试一下。 Hopefully it helps! 希望它会有所帮助!

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM