【问题标题】:Why this Octave code won't work?为什么这个 Octave 代码不起作用?
【发布时间】:2016-07-10 23:44:41
【问题描述】:

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

Y = vec(1:10);

我正在编写必须创建一个N x 10 矩阵的代码,每一行都由除1 之外的所有零组成,仅在与向量Y 中的数字相对应的位置。因此,Y 中的 1 变为 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 的工作变得更容易?

【问题讨论】:

标签: matrix octave


【解决方案1】:

我在 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 中看到的相应值。

另外,请查看此帖子以获取类似示例:Replace specific columns in a matrix with a constant column vector

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

【讨论】:

  • @SerhiiYakovenko 不客气 :) 老实说,我不知道为什么会发生错误......但我建议只索引矩阵的行。效率更高。
  • 非常感谢!我不知道我们可以用索引来做到这一点:)
  • @SerhiiYakovenko 不客气。我不确定我是否回答了你的问题......但我确实做了一些实验来找出问题所在。我把它归结为一些内部错误(如果你可以称之为......)。
【解决方案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

【讨论】:

  • sparse 是我的另一个选择,如果它不是为了索引到单位矩阵。 +1。
猜你喜欢
  • 2018-11-05
  • 2012-02-22
  • 2023-03-03
  • 2017-10-02
  • 2010-12-14
  • 2017-04-09
  • 2013-01-30
  • 2014-05-23
  • 1970-01-01
相关资源
最近更新 更多