我在 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
但是,它是在列而不是行上定义的,但它与您想要实现的非常相似。