【问题标题】:MATLAB: How to count number frequency columnwise, in continuous blocksMATLAB:如何在连续块中按列计算数字频率
【发布时间】:2017-11-09 01:38:46
【问题描述】:

我在 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 次。如您所见,重复次数是根据元素值而不是元素出现的列数排序的。

【问题讨论】:

  • 块是否总是用零分隔?
  • 是的,他们会@LuisMendo

标签: matlab matrix frequency


【解决方案1】:

由于您不关心列,您可以将所有列串成一个列向量,并在两端填充零以防止列的开头和结尾处的跨度一起运行:

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);

现在,假设 span 总是由 1 个或多个零分隔,您可以找到每个 span 的长度如下:

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】:

困难的部分是找到并分离块。 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}).';

【讨论】:

    【解决方案3】:
    b = {}
    for i = 1:ncolumns
        for n = 1:nnumbers
            b{i}(n) = sum(a(:,i) == n)
        end
    end
    

    (请注意,这将为计数为 0 的数字设置零,否则我看不出您还能如何识别正在计数的值)

    【讨论】:

    • 感谢您的帮助。我不介意 0,问题是这样可以获得一个值出现的总次数(例如,当我想获得 4,3 时,值 2 为 7)。此外,频率的计数顺序是列的顺序,而不是值的顺序。
    猜你喜欢
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    相关资源
    最近更新 更多