迭代矩阵列的最佳方法是什么?
我想使用 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)));
有什么问题吗这段代码? 我该如何改进它?
I want to apply a function to all columns in a matrix with MATLAB. For example, I'd like to be able to call smooth on every column of a matrix, instead of having smooth treat the matrix as a vector (which is the default behaviour if you call smooth(matrix)
).
I'm sure there must be a more idiomatic way to do this, but I can't find it, so I've defined a map_column
function:
function result = map_column(m, func)
result = m;
for col = 1:size(m,2)
result(:,col) = func(m(:,col));
end
end
which I can call with:
smoothed = map_column(input, @(c) (smooth(c, 9)));
Is there anything wrong with this code? How could I improve it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
MATLAB“for”语句实际上循环遍历所提供的任何内容的列 - 通常,这只会产生标量序列,因为传递给 for 的向量(如上面的示例所示)是行向量。 这意味着您可以像这样重写上面的代码:
如果 func 不返回列向量,那么您可以添加类似的内容
以将其强制放入列中。
The MATLAB "for" statement actually loops over the columns of whatever's supplied - normally, this just results in a sequence of scalars since the vector passed into for (as in your example above) is a row vector. This means that you can rewrite the above code like this:
If func does not return a column vector, then you can add something like
to force it into a column.
你的解决方案很好。
请注意,horizcat 对于大型矩阵会造成严重的性能损失。 它使代码的复杂度为 O(N^2) 而不是 O(N)。 对于 100x10,000 矩阵,您的实现在我的机器上需要 2.6 秒,horizcat 需要 64.5 秒。 对于 100x5000 矩阵,horizcat 实现需要 15.7 秒。
如果您愿意,您可以稍微概括您的函数,并使其能够迭代最终维度甚至任意维度(不仅仅是列)。
Your solution is fine.
Note that horizcat exacts a substantial performance penalty for large matrices. It makes the code be O(N^2) instead of O(N). For a 100x10,000 matrix, your implementation takes 2.6s on my machine, the horizcat one takes 64.5s. For a 100x5000 matrix, the horizcat implementation takes 15.7s.
If you wanted, you could generalize your function a little and make it be able to iterate over the final dimension or even over arbitrary dimensions (not just columns).
也许您总是可以使用 ' 运算符转换矩阵,然后将结果转换回来。
这至少适用于 fft 函数。
Maybe you could always transform the matrix with the ' operator and then transform the result back.
That at least works with the fft function.
引起矩阵列间隐式循环的一种方法是使用 cellfun。 也就是说,您必须首先将矩阵转换为元胞数组,每个元胞将保存一列。 然后打电话给cellfun。 例如:
请参阅此处,我计算了每列的标准差。
当然,MATLAB 中的许多函数已设置为按照用户指示处理数组的行或列。 当然 std 也是如此,但这是测试 cellfun 是否成功运行的便捷方法。
A way to cause an implicit loop across the columns of a matrix is to use cellfun. That is, you must first convert the matrix to a cell array, each cell will hold one column. Then call cellfun. For example:
See that here I've computed the standard deviation for each column.
Of course, many functions in MATLAB are already set up to work on rows or columns of an array as the user indicates. This is true of std of course, but this is a convenient way to test that
cellfun
worked successfully.如果您正在处理大型矩阵,请不要忘记预先分配结果矩阵。 否则,每次添加新行/列时,您的 CPU 将花费大量周期重复重新分配矩阵。
Don't forget to preallocate the result matrix if you are dealing with large matrices. Otherwise your CPU will spend lots of cycles repeatedly re-allocating the matrix every time it adds a new row/column.
如果这是您的函数的常见用例,那么如果输入不是向量,则让函数自动迭代列可能是个好主意。
这并不能完全解决您的问题,但它会简化函数的使用。 在这种情况下,输出也应该是一个矩阵。
您还可以使用
m(:,:) = m(:)
将矩阵转换为一长列。 但是,这是否有意义取决于您的职能。If this is a common use-case for your function, it would perhaps be a good idea to make the function iterate through the columns automatically if the input is not a vector.
This doesn't exactly solve your problem but it would simplify the functions' usage. In that case, the output should be a matrix, too.
You can also transform the matrix to one long column by using
m(:,:) = m(:)
. However, it depends on your function if this would make sense.