使用arrayfun向量化输出一行并返回矩阵的函数

8
我正在使用Octave,并希望将一个接受单个实数作为输入并输出固定长度行向量的函数矢量化。我了解到,从其不清晰的文档中可以使用arrayfun来完成这项工作。从Octave 3.2的help arrayfun中得知:

如果在进一步的字符串输入参数“UniformOutput”之后设置参数VAL为“true”(默认值),则命名函数FUNC必须返回一个单元素,然后将被连接到返回值中并且是矩阵类型。否则,如果该参数设置为“false”,则输出将连接在单元格数组中。

然而,似乎Matlab的版本更加宽容

= arrayfun(func,A1,...,An) 调用由函数句柄func指定的函数,并传递来自数组A1,...,An的元素,其中n是函数func的输入数量。 输出数组B1,...,Bm(其中m是函数func的输出数),包含来自函数调用的组合输出。第i次迭代对应于语法[B1(i),...,Bm(i)] = func(A1 {i},...,An {i})。 arrayfun函数不按特定顺序执行对函数func的调用。这似乎在Matlab中有效,但在Octave中无效。我正确吗?是否有更聪明的方法可以实现此目标而不使用非向量化循环?

octave:5> nums
nums =

@(c) ([c, c + 2, c + 4])

octave:6> arrayfun(nums,[1,2,3])
错误:cellfun期望UniformOutput=true时所有值都为标量
错误:调用自:
错误: /opt/local/share/octave/3.2.4/m/general/arrayfun.m,第168行,第21列
octave:6>


为什么你坚持使用arrayfun?试试简单的for循环,然后就完成了。 - Shai
@Shai http://zh.wikipedia.org/wiki/向量化_(并行计算) - djechlin
@djechlin:https://dev59.com/questions/zWcs5IYBdhLWcg3w3HkG - Daniel
@DanielR 那个答案是针对Matlab的,而这位OP明确表示他正在使用Octave。建议他在那里使用for循环是不合适的。 - carandraug
2个回答

3
使用 arrayfun 将函数 nums 应用于数组 [1,2,3]。
CellArray = arrayfun(nums, [1,2,3], "UniformOutput", false);

这将给你一个单元数组。如果您想要矩阵中的答案,请使用cell2mat

cell2mat(CellArray);

如果你的实际 nums更复杂,那么我们需要更好的例子来建议解决方案。

arrayfun"UniformOutput", false一起使用会返回一个“行”单元数组(即沿第二维)。而nums的输出也是行向量(即沿第二维)。cell2mat将它们连接成一个长行向量。为了获得矩阵,首先需要将单元数组重塑为预期的连接维度:cell2mat(reshape(CellArray, numel(CellArray), 1)) - ederag
你也可以简单地转置向量 arrayfun(nums, [1,2,3].', "UniformOutput", false); 以得到一个列单元数组。注意 [1,2,3] 的转置! - Jan

1
错误已经提示如何解决问题:
arrayfun(nums,[1,2,3],'UniformOutput',false)

没有Matlab和Octave之间的区别。
Matlab:
>> nums=@(c) ([c, c + 2, c + 4])

nums = 

    @(c)([c,c+2,c+4])

EDU>> arrayfun(nums,[1,2,3])
Error using arrayfun
Non-scalar in Uniform output, at
index 1, output 1.
Set 'UniformOutput' to false.

>> arrayfun(nums,[1,2,3],'UniformOutput',false)

ans = 

  Columns 1 through 2

    [1x3 double]    [1x3 double]

  Column 3

    [1x3 double]

Octave:

octave:1> nums=@(c) ([c, c + 2, c + 4])
nums =

@(c) ([c, c + 2, c + 4])

octave:2> arrayfun(nums,[1,2,3])
error: arrayfun: all values must be scalars when UniformOutput = true
octave:2> arrayfun(nums,[1,2,3],'UniformOutput',false)
ans = 
{
  [1,1] =

     1   3   5

  [1,2] =

     2   4   6

  [1,3] =

     3   5   7

}
octave:3> 

如果你的函数确实很简单,我建议使用:
nums([1,2,3]')

不幸的是,我的实际 nums 有点复杂。它更像是 nums = @(c)(other_function(c, curried_argument))。我认为这就是你上次解决方案失败的原因。是的,我可以禁用 UniformOutput 并转换输出,这可能是最优雅的做法,但仍在研究中。 - djechlin
@djechlin 如果可能的话,你应该考虑将other_function编写为接受向量。 - carandraug
@carandraug 我不拥有它。(这是fmincg。) - djechlin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接