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

在MATLAB中将不同长度的列向量连接到矩阵中的最佳方法,matlab,matrix,Matlab,Matrix,假设我有一系列长度不同的列向量,从计算时间的角度来说,最好的方法是将它们连接到一个矩阵中,其中它的大小由最长的列决定,并且拉长的列单元格都填充有NaN 编辑:请注意,我试图避免使用单元格数组,因为它们在内存和运行时间方面都很昂贵 例如: A = [1;2;3;4]; B = [5;6]; C = magicFunction(A,B); 结果: C = 1 5 2 6 3 NaN 4 NaN 如果使用单元矩阵,则不需要用NaN填充它们,只需将每个数组写入一列,未使用的元

假设我有一系列长度不同的列向量,从计算时间的角度来说,最好的方法是将它们连接到一个矩阵中,其中它的大小由最长的列决定,并且拉长的列单元格都填充有NaN

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

例如:

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

C = magicFunction(A,B);
结果:

C =
  1  5
  2  6
  3 NaN
  4 NaN

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

 cell_result{1} = A;
 cell_result{2} = B; 
这将产生一个大小为2的单元格数组,其中包含his元素中a、B的所有元素。或者,如果希望将它们另存为列:

 cell_result(1,1:numel(A)) = num2cell(A);
 cell_result(2,1:numel(B)) = num2cell(B); 
如果您需要为将来的编码填充NaN的,那么最容易找到您得到的最大长度。自己创建一个矩阵(最大长度X阵列数)

假设有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;

下面的代码避免使用
单元数组
,除了估计每个向量中的元素数量之外,这使代码更干净。使用
单元阵列
完成这一点点工作的价格应该不会太贵。另外,
varargin
会以单元格数组的形式获取输入。现在,您也可以避免使用单元格数组,但这很可能涉及使用
for循环
,并且可能必须为每个输入使用变量名,这在创建具有未知输入数的函数时并不太优雅。否则,代码将使用
数字数组
逻辑索引
和我最喜欢的
bsxfun
,这在运行时市场上肯定很便宜

功能代码

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;
示例

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

基准测试

作为基准测试的一部分,我们将我们的解决方案与主要基于单元阵列的解决方案进行比较。我们在这里的意图是,在避免使用电池阵列之后,如果有任何加速,我们会得到什么。以下是带有
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.
结论-

  • 对于
    20
    矢量和最大长度
    1500000
    ,加速比介于
    2-3x
    之间,可以看出加速比随着矢量数量的增加而增加。证明这一点的结果并不是为了节省空间,因为我们已经在这里使用了很多

  • 在写下我的解决方案后,我发现这个解决方案非常有用。检查gnovice的解决方案。谢谢,我今天稍后会尝试这些解决方案。因为它们在内存和运行时间方面都很昂贵,所以我尽量避免使用单元格数组。@EitanVesely在问题中添加了此注释,这样人们就不会将其作为链接问题的重复内容。@EitanVesely这太好了!:)