为什么这个Octave代码不起作用?

时间:2016-03-23 15:29:53

标签: matrix octave

Y成为长度为N的向量,其中包含从110的数字。作为示例代码,您可以使用:

Y = vec(1:10);

我正在编写必须创建N x 10矩阵的代码,每行除了1之外的所有零都包含在与向量Y中的数字对应的位置。因此,1中的Y变为100000000003变为0010000000,依此类推。

这种方法有效:

cell2mat(arrayfun(@(x)eye(10)(x,:), Y, 'UniformOutput', false))

我的下一个想法是“优化”,因此eye(10)未生成N次,我写了这个:

theEye = eye(10);
cell2mat(arrayfun(@(x)theEye(x,:), Y, 'UniformOutput', false))

然而,现在Octave给了我错误:

error: can't perform indexing operations for diagonal matrix type
error: evaluating argument list element number 1

为什么会出现此错误?有什么问题?

奖金问题 - 您是否看到了更好的方式来做我正在做的事情?我是否试图优化Octave的制作工作?

2 个答案:

答案 0 :(得分:4)

我在Octave中运行此代码,eye创建了一个类(或其他任何类)的矩阵,称为Diagonal Matrix

octave:3> theEye = eye(10);
octave:4> theEye
theEye =

Diagonal Matrix

   1   0   0   0   0   0   0   0   0   0
   0   1   0   0   0   0   0   0   0   0
   0   0   1   0   0   0   0   0   0   0
   0   0   0   1   0   0   0   0   0   0
   0   0   0   0   1   0   0   0   0   0
   0   0   0   0   0   1   0   0   0   0
   0   0   0   0   0   0   1   0   0   0
   0   0   0   0   0   0   0   1   0   0
   0   0   0   0   0   0   0   0   1   0
   0   0   0   0   0   0   0   0   0   1

事实上,Octave的文档说如果矩阵是对角线,则会创建一个特殊对象来处理对角矩阵而不是标准矩阵:https://www.gnu.org/software/octave/doc/interpreter/Creating-Diagonal-Matrices.html

有趣的是,我们可以在arrayfun调用之外切换到此矩阵,无论它是否在单独的类中。

octave:1> theEye = eye(10);
octave:2> theEye(1,:)
ans =

Diagonal Matrix

   1   0   0   0   0   0   0   0   0   0

然而,只要我们将其置于arrayfun电话中,它就会决定废话:

octave:5> arrayfun(@(x)theEye(x,:), 1:3, 'uni', 0)
error: can't perform indexing operations for diagonal matrix type

这对我来说没有任何意义,特别是因为我们可以在arrayfun之外切入它。有人可能会怀疑它与arrayfun有关,并且由于您指定UniformOutput为false,因此Y中的每个元素都会返回一个元素的单元格数组,并且可能出现了问题将这些切片存储到每个单元数组元素中时。

然而,这似乎也不是罪魁祸首。我取了theEye的前三行,将它们放入一个单元格数组中,并使用cell2mat将它们合并在一起:

octave:6> cell2mat({theEye(1,:); theEye(2,:); theEye(3,:)})
ans =

   1   0   0   0   0   0   0   0   0   0
   0   1   0   0   0   0   0   0   0   0
   0   0   1   0   0   0   0   0   0   0

因此,我怀疑它可能是某种内部错误(如果你可以称之为......)。 感谢用户carandraug(见上面的评论),这确实是一个错误,并且已经报告:https://savannah.gnu.org/bugs/?47510。还可以提供深刻见解的是,此代码在MATLAB中按预期运行。

无论如何,你可以从中得到的一点是,我会严肃地避免使用cell2mat。只需使用直接索引:

Y = vec(1:10);
theEye = eye(10);
out = theEye(Y,:);

这将索引到theEye并提取存储在Y中的相关行,并创建一个矩阵,其中每行为零,除了在每个元素Y中看到的相应值。< / p>

另外,请看一下类似示例的帖子:Replace specific columns in a matrix with a constant column vector

但是,它是在列而不是行上定义的,但它与您想要实现的非常相似。

答案 1 :(得分:2)

另一种方法;我们从数据开始:

>> len = 10;                % max number
>> vec = randi(len, [1 7])  % vector of numbers
vec =
     1    10     9     5     7     3     6

现在我们构建指标矩阵:

>> I = full(sparse(1:numel(vec), vec, 1, numel(vec), len))
I =
     1     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     1
     0     0     0     0     0     0     0     0     1     0
     0     0     0     0     1     0     0     0     0     0
     0     0     0     0     0     0     1     0     0     0
     0     0     1     0     0     0     0     0     0     0
     0     0     0     0     0     1     0     0     0     0