MATLAB:如何在连续的块

时间:2017-06-07 15:35:17

标签: matlab matrix frequency

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

a = zeros(10,3); 
a(3:6,1)=2; a(5:9,3)=1; a(5:7,2)=3; a(8:10,1)=2;

a =
 0     0     0
 0     0     0
 2     0     0
 2     0     0
 2     3     1
 2     3     1
 0     3     1
 2     0     1
 2     0     1
 2     0     0

我想获得一个单元格数组,其中包含每个数字出现在列中的次数。此外,无论列号如何,都应根据元素值进行排序。在上面的例子中,我想获得单元格:

b = {[5],[4,3],[3]}

因为数字1出现一次5次,数字2出现在4和3的块中两次,而数字3出现3次。如您所见,重复是根据元素值排序的,而不是元素出现的列数。

3 个答案:

答案 0 :(得分:3)

困难的部分是找到并分离块。 diff将找到任何数字运行的起点,这是此解决方案的起点:

b = [zeros(1,size(a,2)); a; zeros(1,size(a,2))];
idx = diff(b)~=0;
block_values = b(idx);
block_lengths = diff([0; find(idx)]);

现在我们有两个向量的每个块的值,它们有多长,它们只需要在单元格数组中捕获,忽略零块

c = accumarray(block_values(block_values~=0), block_lengths(block_values~=0), [], @(x) {x}).';

答案 1 :(得分:3)

由于您不关心该列,因此您可以将所有列都串在一个列向量中,在任一端填充零,以防止列的开头和结尾的跨距一起运行:

v = reshape(padarray(a, [1 0]), [], 1);
% Or if you don't have the Image Processing Toolbox function padarray...
v = reshape([zeros(1, size(a, 2)); a; zeros(1, size(a, 2))], [], 1);

现在,假设跨度总是以1或更多的零分隔,您可以按如下方式找到每个跨度的长度:

endPoints = find(diff(v) ~= 0);  % Find where transitions to or from 0 occur
spans = endPoints(2:2:end)-endPoints(1:2:end); % Index of transitions to 0 minus
                                               % index of transitions from 0

最后,根据这些跨度中的值,您可以accumulate跨度:

b = accumarray(v(endPoints(1:2:end)+1), spans, [], @(v) {v(:).'}).';

以你的例子为例:

b =

  1×3 cell array

    [5]    [1×2 double]    [3]

注意:

结果单元格数组中值的排序不能保证与spans中的顺序匹配(即上面b{2}[3 4]而不是[4 3])。如果订单很重要,您需要对下标as per this section of the documentation进行排序。以下是如何更改b

的计算方法
[vals, index] = sort(v(endPoints(1:2:end)+1));
b = accumarray(vals, spans(index), [], @(v) {v(:).'}).';

答案 2 :(得分:0)

b = {}
for i = 1:ncolumns
    for n = 1:nnumbers
        b{i}(n) = sum(a(:,i) == n)
    end
end

(请注意,这会为计数为0的数字设置零,但我不知道你怎么能识别哪个值被计算在内)