MATLAB / Octave:使用索引数组递增数组

3

我正在努力优化一段代码。 我需要处理许多数字(百万级别),但代码运行缓慢。 假设我们有一个3x3的矩阵:

A = [ 8 1 6; 3 5 7; 4 9 2 ];

我想知道区间 [0, 3), [3, 6) 和 [6, 9) 中有多少个元素。因此,我需要一个 1x3 的矩阵:
p = [ 2 3 4 ];

我的代码是:
p = zeros(1, 3);
for i = 1 : 9
   p( floor(A / 3) + 1 ) += 1;

我想不用 for 循环来完成它,但代码是:
p = zeros(1, 3);
p( floor(A / 3) + 1 ) += 1;

输出:
p = 1 1 1

任何想法是为什么?我该如何纠正这个问题?
2个回答

2
你正在实现的是一个直方图:
p=histc(A(:),[0,3,6,9]); %For MATLAB 2014b or newer use histcounts instead

它返回 p=[2,3,3,1],因为它隐式创建了一个区间[9,inf)

为了解释索引问题。在MATLAB中不支持对同一索引的多次赋值。它们总是采用最后一次赋值:

x=zeros(3,1)
x([1,1,2,1])=[1,2,3,4] %results in x(1)=4

对于增量运算符,同样适用相同的规则。它的行为类似于:

x([1,1,1,1])=x([1,1,1,1])+1

对于这种多重赋值的一般情况,您可以使用accumarray:

%assume you want x([1,1,2,1])=[1,2,3,4]
accumarray([1,1,1,1].',[1,2,3,4].')
%results in [7,3]

1

直方图箱计数

正如丹尼尔在他的回答中所写的,您正在计算直方图箱中值的计数。使用较新的histcounts命令(建议用于较新版本的Matlab)是一种替代方法。

A = [ 8 1 6; 3 5 7; 4 9 2 ];
[p, ~, ~] = histcounts(A, 0:3:9);

%// p = 2     3     4

矩阵关系运算符后跟非零元素数量

您还可以使用矩阵关系运算符后跟 nnz 命令来计算非零元素的数量:

A = [ 8 1 6; 3 5 7; 4 9 2 ];
p = [nnz(A < 3);
    nnz(A >= 3 & A < 6);
    nnz(A >= 6)];         %// alternatively nnz(A >= 6 & A < 9) for the last entry

%// ...

p =

     2
     3
     4

"最快的?"

通过一些快速的tic/toc测试,似乎在我的系统上(运行Matlab R2014b),后者的nnz方法比:

  • 使用histcounts方法要快3-4倍。
  • 使用旧版hist命令的直方图方法要快5-6倍。

然而,我没有尝试过在A变得更大时如何扩展,以防这是您应用程序的情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接