我想用MATLAB将函数应用于矩阵中的所有列。例如,我希望能够在矩阵的每一列上调用平滑,而不是将矩阵平滑地视为向量(如果您调用 smooth(matrix),这是默认行为) )。

我确信必须有更惯用的方法来做到这一点,但我找不到它,所以我已经定义了 map_column 函数:

function result = map_column(m, func)
    result = m;
    for col = 1:size(m,2)
        result(:,col) = func(m(:,col));
    end
end

我可以打电话:

smoothed = map_column(input, @(c) (smooth(c, 9)));

这段代码有什么问题吗?我怎么能改进它?

有帮助吗?

解决方案

你的解决方案很好。

请注意,对于大型矩阵,horizcat会严重影响性能。它使代码为O(N ^ 2)而不是O(N)。对于100x10,000矩阵,我的机器上的实现需要2.6秒,而horizcat需要64.5秒。对于100x5000矩阵,horizcat实现需要15.7秒。

如果您愿意,可以稍微概括一下您的函数,使其能够迭代最终维度甚至任意维度(不仅仅是列)。

其他提示

MATLAB“for”语句实际上循环遍历任何提供的列 - 通常,这只会产生一系列标量,因为传入的向量(如上例所示)是一个行向量。这意味着你可以像这样重写上面的代码:

function result = map_column(m, func)
    result = [];
    for m_col = m
      result = horzcat(result, func(m_col));
    end

如果func没有返回列向量,那么您可以添加类似

的内容
f = func(m_col);
result = horzcat(result, f(:));

强制它进入一列。

也许您总是可以使用'运算符转换矩阵,然后将结果转换回来。

smoothed = smooth(input', 9)';

至少适用于fft功能。

在矩阵的列中引入隐式循环的方法是使用cellfun。也就是说,您必须首先将矩阵转换为单元格数组,每个单元格将包含一列。然后打电话给cellfun。例如:

A = randn(10,5);

在这里看到我已计算出每列的标准偏差。

cellfun(@std,mat2cell(A,size(A,1),ones(1,size(A,2))))

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482

当然,MATLAB中的许多函数已经设置为按用户指示的方式处理数组的行或列。当然,std也是如此,但这是测试 cellfun 成功运行的便捷方法。

std(A,[],1)

ans =
      0.78681       1.1473      0.89789      0.66635       1.3482

如果处理大型矩阵,请不要忘记预先分配结果矩阵。否则,每次添加新行/列时,CPU将花费大量周期重复分配矩阵。

如果这是函数的常见用例,那么如果输入不是向量,则使函数自动遍历列可能是个好主意。

这并不能完全解决您的问题,但会简化功能的使用。在这种情况下,输出也应该是一个矩阵。

您还可以使用 m(:,:) = m(:)将矩阵转换为一个长列。但是,这取决于你的功能是否有意义。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top