11

我想使用 MATLAB 将函数应用于矩阵中的所有列。例如,我希望能够在矩阵的每一列上调用 smooth ,而不是让 smooth 将矩阵视为向量(如果调用 ,这是默认行为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)));

这段代码有什么问题吗?我该如何改进它?

4

6 回答 6

10

MATLAB“for”语句实际上循环遍历所提供的任何列 - 通常,这只会产生一系列标量,因为传递给 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(:));

强制它进入一列。

于 2008-10-23T18:17:14.143 回答
3

你的解决方案很好。

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

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

于 2008-11-09T07:30:35.883 回答
2

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

smoothed = smooth(input', 9)';

这至少适用于 fft 功能。

于 2008-10-19T15:05:52.753 回答
2

一种在矩阵列之间产生隐式循环的方法是使用 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
于 2009-04-11T02:34:02.390 回答
1

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

于 2008-12-10T18:11:21.013 回答
0

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

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

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

于 2008-10-19T14:15:31.310 回答