matlab - 将向量附加到空的MATLAB矩阵

标签 matlab matrix

我已经用Matlab编写了代码,将N维点(n>1)插入到矩阵(myPointMatrix)中,并且正在考虑如何插入第一个点。
现在程序在插入点之前检查myPointMatrix的大小如果是1x1,myPointMatrix设置为等于当前点否则将附加当前点这个if-语句只有一次是正确的,但是每次我插入一个点时都会对它求值,这是非常常见的。
删除if并尝试附加到myPointMatrix使MATLAB抱怨矩阵维数不一致是可以理解的删除if-语句和myPointMatrix = 0的简化会导致MATLAB发现myPointMatrix未定义也可以理解。
如何初始化myPointMatrix以便删除if-语句还是有其他聪明的解决方案?

myPointMatrix = 0;
for x=0:limit
    for y=0:limit
        for z=0:limit
            tempPoint = [x y z];
            if (length(myPointMatrix) == 1)
                myPointMatrix = tempPoint;
            else
                myPointMatrix = [myPointMatrix; tempPoint];
            end
        end
    end
end

最佳答案

有几种方法可以将矩阵或向量附加到任何矩阵,无论是否为空很大程度上取决于矩阵的大小,以及执行追加的频率(注意稀疏矩阵是完全不同的动物它们需要单独处理。)
简单的方案将使用连接例如,我将创建一个随机数组虽然我知道打一个电话给兰德是正确的解决方案,但我这样做只是为了比较。

n = 10000;
tic
A = [];
for i = 1:n
  Ai = rand(1,3);
  A = [A;Ai];
end
toc

Elapsed time is 9.537194 seconds.

要知道,所需的时间相当高,远远超过我刚刚直接打电话给兰德。
tic,rand(n,3);toc
Elapsed time is 0.008036 seconds.

其他的附加方式在时间上是相似的例如,也可以通过索引追加。
A = [];
A(end+1,:) = rand(1,3);
A
A =
      0.91338      0.63236      0.09754

从时间上看,这与通过连接追加相似要理解的一个有趣的事实是,向数组追加新行与追加新列有细微的不同附加行所需的时间比附加列所需的时间稍长这是因为元素在MATLAB中的存储方式追加新行意味着这些元素实际上必须在内存中无序排列。
A = zeros(10000,3);
B = zeros(3,10000);

tic,for i = 1:100,A(end+1,:) = rand(1,3);end,toc
Elapsed time is 0.124814 seconds.

tic,for i = 1:100,B(:,end+1) = rand(3,1);end,toc
Elapsed time is 0.116209 seconds.

任何追加操作的问题是,Matlab必须重新分配A所需的内存,并且每次矩阵增大时都必须这样做。由于a的大小是线性增长的,所以所需的总时间与n成二次增长,因此如果我们将n的大小加倍,动态增长的a将需要4倍的时间来构建。这种二次型行为就是为什么人们告诉你在动态增长时预先分配你的MATLAB数组实际上,如果您在编辑器中查看mlint标志,当看到这种情况时,MATLAB会发出警告。
如果您知道A的最终大小,一个更好的解决方案是将A预先分配给它的最终大小然后索引进去。
tic
A = zeros(n,3);
for i = 1:n
  A(i,:) = rand(1,3);
end
toc

Elapsed time is 0.156826 seconds.

虽然这比动态增长的数组好得多,但仍然比rand的矢量化使用差得多。所以在可能的情况下,使用这样的向量化形式的函数。
问题是,有时候你根本不知道最终会有多少元素。仍然有一些技巧可以用来避免讨厌的二次增长。
一个诀窍是猜测A的最终大小。现在,使用索引将新的值插入到A中,但是仔细观察新的条目何时会溢出A的边界。当这即将发生时,将A的大小加倍,将一个大的零块附加到末尾。现在返回索引新的元素到A。保持一个单独的计数有多少元素已经“追加”。在这个过程的最后,删除未使用的元素这避免了许多讨厌的二次行为,因为只有几个附加步骤将永远完成(请记住,在必须执行追加操作时,要将A的大小加倍。)
第二个技巧是使用指针虽然MATLAB在指针方面并没有提供太多功能,但是单元数组是朝着这个方向迈出的一步。
tic
C = {};
for i = 1:n
  C{end+1} = rand(1,3);
end
A = cat(1,C{:});
toc

Elapsed time is 3.042742 seconds.

这比成长的阵列花更少的时间来完成为什么?我们只是建立了一个指向单元格的指针数组这方面的一个好处是,如果每个append步骤都有可变的行数,那么它仍然可以很好地工作。
单元格数组的一个问题是,当有数百万个元素要追加时,它的效率不是很高毕竟这仍然是一个二次运算,因为我们在每一步都在增加指针数组。
解决这个问题的方法是使用上面显示的两种样式的混合体因此,将单元数组的每个单元定义为中等大小现在使用索引将新的A行填充到单元格中。当下一个追加步骤必须增大当前单元格时,只需向单元格数组中添加一个新单元格。
几年前,在MATLAB新闻组上出现了这种讨论,并提出了一些解决方案我把这些解决方案作为文件发布到MATLAB中央文件交换上Growdata2使用函数句柄来解决问题:
tic
Ahandle = growdata2;
for i = 1:n
  Ahandle(rand(1,3))
end
% unpack the object into a normal array
A = Ahandle();
toc

Elapsed time is 1.572798 seconds.

当时,使用持久变量是一种更快的方法。
tic
growdata
for i = 1:n
  growdata(rand(1,3))
end
A = growdata;
toc

Elapsed time is 2.048584 seconds.

从那时起,函数句柄的实现在MATLAB中有了明显的改进,因此函数句柄现在更快了。
这些方案的一个优点是它们不会有二次性能惩罚,同时允许数百万个附加步骤。
哦,好吧,这肯定比问问题时最初要求的信息要多也许有人会从中得到一些东西。

关于matlab - 将向量附加到空的MATLAB矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/781410/

相关文章:

matlab - 使用Matlab修改文本文件

python - 从其上三角初始化一个对称的 Theano dmatrix

康威的生命游戏,数邻居

python - 有没有办法获得 numpy 中的最大值矩阵?

arrays - isnan 索引

matlab - 在 Matlab 中转发输入名称?

arrays - 在 MATLAB 中从 Nx1 向量创建所有可能的 Mx1 向量

matlab - 如何自动为 fmincon 找到合适的初始值?

haskell - 矩阵的第一列作为 Haskell 中的行列表给出

java - Java 中的矩阵幂不准确