对于使用嵌套调用permute 的答案有很多人赞成,我想到了计时并与使用mat2cell 的其他答案进行比较。
的确,他们不会返回完全相同的东西,但是:
- 可以轻松地将单元格转换为与其他单元格一样的矩阵(我对此进行了计时,请参阅下文);
- 当出现此问题时,最好(根据我的经验)将数据放在一个单元格中,因为稍后人们通常希望将原始数据重新组合在一起;
无论如何,我已经将它们与以下脚本进行了比较。代码在 Octave(版本 3.9.1)中运行,并禁用了 JIT。
function T = split_by_reshape_permute (A, m, n)
T = permute (reshape (permute (reshape (A, size (A, 1), n, []), [2 1 3]), n, m, []), [2 1 3]);
endfunction
function T = split_by_mat2cell (A, m, n)
l = size (A) ./ [m n];
T = mat2cell (A, repmat (m, l(1), 1), repmat (n, l (2), 1));
endfunction
function t = time_it (f, varargin)
t = cputime ();
for i = 1:100
f(varargin{:});
endfor
t = cputime () - t;
endfunction
Asizes = [30 50 80 100 300 500 800 1000 3000 5000 8000 10000];
Tsides = [2 5 10];
As = arrayfun (@rand, Asizes, "UniformOutput", false);
for d = Tsides
figure ();
t1 = t2 = [];
for A = As
A = A{1};
s = rows (A) /d;
t1(end+1) = time_it (@split_by_reshape_permute, A, s, s);
t2(end+1) = time_it (@split_by_mat2cell, A, s, s);
endfor
semilogy (Asizes, [t1(:) t2(:)]);
title (sprintf ("Splitting in %i", d));
legend ("reshape-permute", "mat2cell");
xlabel ("Length of matrix side (all squares)");
ylabel ("log (CPU time)");
endfor
注意 Y 轴是对数刻度
性能
在性能方面,对于较小的矩阵,使用嵌套置换只会更快,因为相对性能的大变化实际上是非常小的时间变化。请注意,Y 轴采用 对数刻度,因此 100x100 矩阵的两个函数之间的差异为 0.02 秒,而 10000x10000 矩阵的两个函数之间的差异为 100 秒。
我还测试了以下内容,它将单元格转换为矩阵,以便两个函数的返回值相同:
function T = split_by_mat2cell (A, m, n)
l = size (A) ./ [m n];
T = mat2cell (A, repmat (m, l(1), 1), repmat (n, l (2), 1), 1);
T = reshape (cell2mat (T(:)'), [m n numel(T)]);
endfunction
这确实会减慢速度,但不足以考虑(线条将在 600x600 而不是 400x400 处交叉)。
可读性
要理解嵌套置换和重塑的使用要困难得多。使用它很疯狂。它会增加很多维护时间(但是,这是 Matlab 语言,它不应该是优雅和可重用的)。
未来
对 permute 的嵌套调用根本无法很好地扩展到 N 维。我想这将需要一个按维度的 for 循环(这对已经非常神秘的代码毫无帮助)。另一方面,利用mat2cell:
function T = split_by_mat2cell (A, lengths)
dl = arrayfun (@(l, s) repmat (l, s, 1), lengths, size (A) ./ lengths, "UniformOutput", false);
T = mat2cell (A, dl{:});
endfunction
编辑(也在 Matlab 中测试过)
对建议使用 permute 和 reshape 的答案的投票数量让我非常好奇,因此我决定在 Matlab (R2010b) 中进行测试。结果几乎相同,即它的性能真的很差。所以除非这个操作会被做很多次,在总是很小(小于 300x300)的矩阵中,并且总会有一个 Matlab 大师来解释它的作用,不要使用它。