在MATLAB中将不同长度的列向量连接到矩阵的最佳方法

时间:2014-08-28 07:23:01

标签: matlab matrix

假设我有一系列具有不同长度的列向量,那么就计算时间而言,最好的方法是将它们连接成一个矩阵,其中它的大小由最长列和细长柱细胞全都充满了NaN。

编辑:请注意我正在尝试避免使用单元格数组,因为它们在内存和运行时方面都很昂贵。

例如:

A = [1;2;3;4]; 
B = [5;6];

C = magicFunction(A,B);

结果:

C =
  1  5
  2  6
  3 NaN
  4 NaN

2 个答案:

答案 0 :(得分:1)

以下代码避免使用cell arrays,除了估计每个向量中的元素数量,这样可以使代码更清晰。使用cell arrays进行这一小部分工作的代价不应该太昂贵。此外,varargin无论如何都会将输入作为单元格数组。现在,您也可以避免使用单元格数组,但最有可能涉及使用for-loops,并且可能必须为每个输入使用变量名称,这在创建未知函数时并不太优雅。输入数量。否则,代码会使用numeric arrayslogical indexing和我最喜欢的bsxfunmarket of runtimes中的代码必须很便宜。

功能代码

function out = magicFunction(varargin)

lens = cellfun(@(x) numel(x),varargin);
out = NaN(max(lens),numel(lens));
out(bsxfun(@le,[1:max(lens)]',lens)) = vertcat(varargin{:}); %//'

return;

示例

脚本 -

A1 = [9;2;7;8];
A2 = [1;5];
A3 = [2;6;3];
out = magicFunction(A1,A2,A3)

输出 -

out =
     9     1     2
     2     5     6
     7   NaN     3
     8   NaN   NaN

基准测试

作为基准测试的一部分,我们将我们的解决方案与@gnovice's solution进行比较,该解决方案主要基于使用单元阵列。我们打算在避免单元阵列之后看到,如果有的话,我们会得到什么样的加速。这是使用20向量的基准代码 -

%// Let's create row vectors A1,A2,A3.. to be used with @gnovice's solution
num_vectors = 20;
max_vector_length = 1500000;
vector_lengths = randi(max_vector_length,num_vectors,1);
vs =arrayfun(@(x) randi(9,1,vector_lengths(x)),1:numel(vector_lengths),'uni',0);
[A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20] = vs{:};


%// Maximally cell-array based approach used in linked @gnovice's solution
disp('--------------------- With @gnovice''s approach')
tic
tcell = {A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20};
maxSize = max(cellfun(@numel,tcell));    %# Get the maximum vector size
fcn = @(x) [x nan(1,maxSize-numel(x))];  %# Create an anonymous function
rmat = cellfun(fcn,tcell,'UniformOutput',false);  %# Pad each cell with NaNs
rmat = vertcat(rmat{:});
toc, clear tcell maxSize fcn rmat

%// Transpose each of the input vectors to get column vectors as needed
%// for our problem
vs = cellfun(@(x) x',vs,'uni',0); %//'
[A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20] = vs{:};

%// Our solution
disp('--------------------- With our new approach')
tic
out = magicFunction(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,...
    A11,A12,A13,A14,A15,A16,A17,A18,A19,A20);
toc

结果 -

--------------------- With @gnovice's approach
Elapsed time is 1.511669 seconds.
--------------------- With our new approach
Elapsed time is 0.671604 seconds.

结论 -

  1. 使用20向量且最大长度为1500000,加速时间在2-3x之间,并且随着我们增加了向量的数量,可以看出加速增加了。结果证明这里没有显示以节省空间,因为我们已经在这里使用了很多。

答案 1 :(得分:0)

如果使用单元矩阵,则不需要用NaN填充它们,只需将每个数组写入一列,未使用的元素保持为空(这将是节省空间的方式)。你可以使用:

 cell_result{1} = A;
 cell_result{2} = B; 

这会产生一个2号单元格数组,其中包含元素中A,B的所有元素。或者,如果您希望将它们保存为列:

 cell_result(1,1:numel(A)) = num2cell(A);
 cell_result(2,1:numel(B)) = num2cell(B); 

如果您需要使用NaN 来填充以备将来编码,那么最容易找到您获得的最大长度。创建一个(max_length X Number of arrays)矩阵。

所以假设你有n = 5个数组:A,B,C,D和E.

h=zeros(1,n);
h(1)=numel(A);
h(2)=numel(B);
h(3)=numel(C);
h(4)=numel(D);
h(5)=numel(E);
max_No_Entries=max(h);
result= zeros(max_No_Entries,n);
result(:,:)=NaN;
result(1:numel(A),1)=A;
result(1:numel(B),2)=B;
result(1:numel(C),3)=C;
result(1:numel(D),4)=D;
result(1:numel(E),5)=E;