如何将函数应用到MATLAB中的矩阵的每一行?

时间:2020-12-26 21:42:38

You can apply a function to every item in a vector by saying, for example, v + 1, or you can use the function arrayfun. How can I do it for every row/column of a matrix without using a for loop?

你可以对向量中的每一项都应用一个函数,例如,v + 1,或者你可以使用函数arrayfun。我怎么能在不使用for循环的情况下对矩阵的每一行/列做它?

11 个解决方案

#1


67  

Many built-in operations like sum and prod are already able to operate across rows or columns, so you may be able to refactor the function you are applying to take advantage of this.

许多内置的操作,如sum和prod已经能够跨行或跨列操作,因此您可以重构正在应用的函数来利用这一点。

If that's not a viable option, one way to do it is to collect the rows or columns into cells using mat2cell or num2cell, then use cellfun to operate on the resulting cell array.

如果这不是一个可行的选择,一种方法是使用mat2cell或num2cell将行或列收集到单元中,然后使用cellfun对结果的单元数组进行操作。

As an example, let's say you want to sum the columns of a matrix M. You can do this simply using sum:

举个例子,假设你想要对矩阵m的列求和,你可以用求和来做这个

M = magic(10);           %# A 10-by-10 matrixcolumnSums = sum(M, 1);  %# A 1-by-10 vector of sums for each column

And here is how you would do this using the more complicated num2cell/cellfun option:

下面是如何使用更复杂的num2cell/cellfun选项:

M = magic(10);                  %# A 10-by-10 matrixC = num2cell(M, 1);             %# Collect the columns into cellscolumnSums = cellfun(@sum, C);  %# A 1-by-10 vector of sums for each cell

#2


22  

You may want the more obscure Matlab function bsxfun. From the Matlab documentation, bsxfun "applies the element-by-element binary operation specified by the function handle fun to arrays A and B, with singleton expansion enabled."

您可能需要更模糊的Matlab函数bsxfun。在Matlab文档中,bsxfun“将函数句柄fun指定的元素对数组A和B的二进制操作应用到数组中,并启用了单元素扩展”。

@gnovice stated above that sum and other basic functions already operate on the first non-singleton dimension (i.e., rows if there's more than one row, columns if there's only one row, or higher dimensions if the lower dimensions all have size==1). However, bsxfun works for any function, including (and especially) user-defined functions.

@ g新表示,sum和其他基本函数已经在第一个非单例维度(即,如果有多于一行,则为行;如果只有一行,则为列;如果较低的维度都具有size==1,则为高维。但是,bsxfun适用于任何函数,包括(特别是)用户定义的函数。

For example, let's say you have a matrix A and a row vector B. E.g., let's say:

例如,假设你有一个矩阵a和一个行向量b,例如:

A = [1 2 3;     4 5 6;     7 8 9]B = [0 1 2]

You want a function power_by_col which returns in a vector C all the elements in A to the power of the corresponding column of B.

你需要一个函数power_by_col它以向量C的形式返回a中的所有元素到B对应列的幂。

From the above example, C is a 3x3 matrix:

从上面的例子,C是一个3x3矩阵:

C = [1^0 2^1 3^2;     4^0 5^1 6^2;     7^0 8^1 9^2]

i.e.,

也就是说,

C = [1 2 9;     1 5 36;     1 8 81]

You could do this the brute force way using repmat:

你可以用蛮力的方式使用repmat:

C = A.^repmat(B, size(A, 1), 1)

Or you could do this the classy way using bsxfun, which internally takes care of the repmat step:

或者你也可以用bsxfun的优雅方式来做,它在内部负责repmat步骤:

C = bsxfun(@(x,y) x.^y, A, B)

So bsxfun saves you some steps (you don't need to explicitly calculate the dimensions of A). However, in some informal tests of mine, it turns out that repmat is roughly twice as fast if the function to be applied (like my power function, above) is simple. So you'll need to choose whether you want simplicity or speed.

因此,bsxfun为您节省了一些步骤(您不需要显式地计算A的维数)。所以你需要选择你想要简单还是速度。

#3


18  

I can't comment on how efficient this is, but here's a solution:

我无法评价它的效率有多高,但这里有一个解决方案:

applyToGivenRow = @(func, matrix) @(row) func(matrix(row, :))applyToRows = @(func, matrix) arrayfun(applyToGivenRow(func, matrix), 1:size(matrix,1))'% ExamplemyMx = [1 2 3; 4 5 6; 7 8 9];myFunc = @sum;applyToRows(myFunc, myMx)

#4


9  

Building on Alex's answer, here is a more generic function:

基于Alex的回答,这里有一个更通用的功能:

applyToGivenRow = @(func, matrix) @(row) func(matrix(row, :));newApplyToRows = @(func, matrix) arrayfun(applyToGivenRow(func, matrix), 1:size(matrix,1), 'UniformOutput', false)';takeAll = @(x) reshape([x{:}], size(x{1},2), size(x,1))';genericApplyToRows = @(func, matrix) takeAll(newApplyToRows(func, matrix));

Here is a comparison between the two functions:

以下是两个功能的比较:

>> % ExamplemyMx = [1 2 3; 4 5 6; 7 8 9];myFunc = @(x) [mean(x), std(x), sum(x), length(x)];>> genericApplyToRows(myFunc, myMx)ans =     2     1     6     3     5     1    15     3     8     1    24     3>> applyToRows(myFunc, myMx)??? Error using ==> arrayfunNon-scalar in Uniform output, at index 1, output 1.Set 'UniformOutput' to false.Error in ==> @(func,matrix)arrayfun(applyToGivenRow(func,matrix),1:size(matrix,1))'

#5


5  

For completeness/interest I'd like to add that matlab does have a function that allows you to operate on data per-row rather than per-element. It is called rowfun (http://www.mathworks.se/help/matlab/ref/rowfun.html), but the only "problem" is that it operates on tables (http://www.mathworks.se/help/matlab/ref/table.html) rather than matrices.

对于完整性/兴趣,我想补充的是,matlab确实有一个函数,它允许您按每一行而不是每个元素来操作。它被称为rowfun (http://www.mathworks.se/help/matlab/ref/rowfun.html),但唯一的“问题”是它对表(http://www.mathworks.se/help/matlab/ref/table.html)进行操作,而不是对矩阵进行操作。

#6


3  

Adding to the evolving nature of the answer to this question, starting with r2016b, MATLAB will implicitly expand singleton dimensions, removing the need for bsxfun in many cases.

从r2016b开始,MATLAB将隐式地扩展单例维度,在许多情况下消除了对bsxfun的需要,从而增加了这个问题的答案的演变性质。

From the r2016b release notes:

r2016b发行说明:

Implicit Expansion: Apply element-wise operations and functions to arrays with automatic expansion of dimensions of length 1

隐式展开:将元素操作和函数应用到长度为1的数组中

Implicit expansion is a generalization of scalar expansion. With scalar expansion, a scalar expands to be the same size as another array to facilitate element-wise operations. With implicit expansion, the element-wise operators and functions listed here can implicitly expand their inputs to be the same size, as long as the arrays have compatible sizes. Two arrays have compatible sizes if, for every dimension, the dimension sizes of the inputs are either the same or one of them is 1. See Compatible Array Sizes for Basic Operations and Array vs. Matrix Operations for more information.

内隐展开是标量展开的一般化。对于标量展开,标量扩展为与另一个数组相同的大小,以促进元素方面的操作。使用隐式展开,这里列出的元素操作符和函数可以隐式地将它们的输入扩展为相同的大小,只要数组具有兼容的大小。如果对于每个维度,输入的维度大小是相同的,或者其中一个是1,那么两个数组的大小是一致的。有关基本操作和数组与矩阵操作的更多信息,请参阅兼容数组大小。

Element-wise arithmetic operators — +, -, .*, .^, ./, .\Relational operators — <, <=, >, >=, ==, ~=Logical operators — &, |, xorBit-wise functions — bitand, bitor, bitxorElementary math functions — max, min, mod, rem, hypot, atan2, atan2d

For example, you can calculate the mean of each column in a matrix A, and then subtract the vector of mean values from each column with A - mean(A).

例如,你可以计算矩阵a中的每一列的均值,然后用a - mean(a)减去每一列的均值向量。

Previously, this functionality was available via the bsxfun function. It is now recommended that you replace most uses of bsxfun with direct calls to the functions and operators that support implicit expansion. Compared to using bsxfun, implicit expansion offers faster speed, better memory usage, and improved readability of code.

以前,这个功能可以通过bsxfun函数获得。现在建议您使用直接调用支持隐式扩展的函数和操作符来替代bsxfun的大多数用途。与使用bsxfun相比,隐式扩展提供了更快的速度、更好的内存使用和提高代码的可读性。

#7


1  

With recent versions of Matlab, you can use the Table data structure to your advantage. There's even a 'rowfun' operation but I found it easier just to do this:

使用Matlab的最新版本,您可以使用表数据结构来发挥优势。甚至还有一个“rowfun”手术,但我发现这样做更容易:

a = magic(6);incrementRow = cell2mat(cellfun(@(x) x+1,table2cell(table(a)),'UniformOutput',0))

or here's an older one I had that doesn't require tables, for older Matlab versions.

这里有一个旧的,不需要表格的,用旧的Matlab版本。

dataBinner = cell2mat(arrayfun(@(x) Binner(a(x,:),2)',1:size(a,1),'UniformOutput',0)')

#8


0  

The accepted answer seems to be to convert to cells first and then use cellfun to operate over all of the cells. I do not know the specific application, but in general I would think using bsxfun to operate over the matrix would be more efficient. Basically bsxfun applies an operation element-by-element across two arrays. So if you wanted to multiply each item in an n x 1 vector by each item in an m x 1 vector to get an n x m array, you could use:

公认的答案似乎是先转换成单元格,然后使用cellfun对所有单元格进行操作。我不知道具体的应用,但总的来说,我认为使用bsxfun操作矩阵会更有效。基本上,bsxfun在两个数组中逐个元素地应用操作。如果你想用一个n x 1向量中的每一项乘以一个m x 1向量中的每一项得到一个n x m数组,你可以用:

vec1 = [ stuff ];    % n x 1 vectorvec2 = [ stuff ];    $ m x 1 vectorresult = bsxfun('times', vec1.', vec2);

This will give you matrix called result wherein the (i,j) entry will be the ith element of vec1 multiplied by the jth element of vec2.

这会得到一个叫做result的矩阵,其中(i,j)项是向量1的第i个元素乘以向量2的第j个元素。

You can use bsxfun for all sorts of built-in functions, and you can declare your own. The documentation has a list of many built-in functions, but basically you can name any function that accepts two arrays (vector or matrix) as arguments and get it to work.

您可以为各种内置函数使用bsxfun,您可以声明自己的功能。该文档有许多内置函数的列表,但是基本上您可以命名任何接受两个数组(向量或矩阵)作为参数的函数并使其工作。

#9


0  

None of the above answers worked "out of the box" for me, however, the following function, obtained by copying the ideas of the other answers works:

以上的答案对我来说都不是“开箱即用”的,但是,通过复制其他答案的想法获得的以下功能是有效的:

apply_func_2_cols = @(f,M) cell2mat(cellfun(f,num2cell(M,1), 'UniformOutput',0));

It takes a function f and applies it to every column of the matrix M.

它取一个函数f并把它应用到矩阵M的每一列。

So for example:

举个例子:

f = @(v) [0 1;1 0]*v + [0 0.1]';apply_func_2_cols(f,[0 0 1 1;0 1 0 1]) ans =   0.00000   1.00000   0.00000   1.00000   0.10000   0.10000   1.10000   1.10000

#10


-1  

Stumbled upon this question/answer while seeking how to compute the row sums of a matrix.

在寻找如何计算矩阵的行和时,偶然发现了这个问题/答案。

I would just like to add that Matlab's SUM function actually has support for summing for a given dimension, i.e a standard matrix with two dimensions.

我想补充的是Matlab的和函数实际上支持对给定维度I求和。一个二维的标准矩阵。

So to calculate the column sums do:

因此,计算列和的方法是:

colsum = sum(M) % or sum(M, 1)

and for the row sums, simply do

对于行和,只要做

rowsum = sum(M, 2)

My bet is that this is faster than both programming a for loop and converting to cells :)

我敢打赌,这比编写for循环和转换为cell都要快:)

All this can be found in the matlab help for SUM.

所有这些都可以在matlab帮助下求和。

#11


-1  

if you know the length of your rows you can make something like this:

如果你知道行的长度,你可以这样做:

a=rand(9,3);b=rand(9,3); arrayfun(@(x1,x2,y1,y2,z1,z2) line([x1,x2],[y1,y2],[z1,z2]) , a(:,1),b(:,1),a(:,2),b(:,2),a(:,3),b(:,3) )

#1


67  

Many built-in operations like sum and prod are already able to operate across rows or columns, so you may be able to refactor the function you are applying to take advantage of this.

许多内置的操作,如sum和prod已经能够跨行或跨列操作,因此您可以重构正在应用的函数来利用这一点。

If that's not a viable option, one way to do it is to collect the rows or columns into cells using mat2cell or num2cell, then use cellfun to operate on the resulting cell array.

如果这不是一个可行的选择,一种方法是使用mat2cell或num2cell将行或列收集到单元中,然后使用cellfun对结果的单元数组进行操作。

As an example, let's say you want to sum the columns of a matrix M. You can do this simply using sum:

举个例子,假设你想要对矩阵m的列求和,你可以用求和来做这个

M = magic(10);           %# A 10-by-10 matrixcolumnSums = sum(M, 1);  %# A 1-by-10 vector of sums for each column

And here is how you would do this using the more complicated num2cell/cellfun option:

下面是如何使用更复杂的num2cell/cellfun选项:

M = magic(10);                  %# A 10-by-10 matrixC = num2cell(M, 1);             %# Collect the columns into cellscolumnSums = cellfun(@sum, C);  %# A 1-by-10 vector of sums for each cell

#2


22  

You may want the more obscure Matlab function bsxfun. From the Matlab documentation, bsxfun "applies the element-by-element binary operation specified by the function handle fun to arrays A and B, with singleton expansion enabled."

您可能需要更模糊的Matlab函数bsxfun。在Matlab文档中,bsxfun“将函数句柄fun指定的元素对数组A和B的二进制操作应用到数组中,并启用了单元素扩展”。

@gnovice stated above that sum and other basic functions already operate on the first non-singleton dimension (i.e., rows if there's more than one row, columns if there's only one row, or higher dimensions if the lower dimensions all have size==1). However, bsxfun works for any function, including (and especially) user-defined functions.

@ g新表示,sum和其他基本函数已经在第一个非单例维度(即,如果有多于一行,则为行;如果只有一行,则为列;如果较低的维度都具有size==1,则为高维。但是,bsxfun适用于任何函数,包括(特别是)用户定义的函数。

For example, let's say you have a matrix A and a row vector B. E.g., let's say:

例如,假设你有一个矩阵a和一个行向量b,例如:

A = [1 2 3;     4 5 6;     7 8 9]B = [0 1 2]

You want a function power_by_col which returns in a vector C all the elements in A to the power of the corresponding column of B.

你需要一个函数power_by_col它以向量C的形式返回a中的所有元素到B对应列的幂。

From the above example, C is a 3x3 matrix:

从上面的例子,C是一个3x3矩阵:

C = [1^0 2^1 3^2;     4^0 5^1 6^2;     7^0 8^1 9^2]

i.e.,

也就是说,

C = [1 2 9;     1 5 36;     1 8 81]

You could do this the brute force way using repmat:

你可以用蛮力的方式使用repmat:

C = A.^repmat(B, size(A, 1), 1)

Or you could do this the classy way using bsxfun, which internally takes care of the repmat step:

或者你也可以用bsxfun的优雅方式来做,它在内部负责repmat步骤:

C = bsxfun(@(x,y) x.^y, A, B)

So bsxfun saves you some steps (you don't need to explicitly calculate the dimensions of A). However, in some informal tests of mine, it turns out that repmat is roughly twice as fast if the function to be applied (like my power function, above) is simple. So you'll need to choose whether you want simplicity or speed.

因此,bsxfun为您节省了一些步骤(您不需要显式地计算A的维数)。所以你需要选择你想要简单还是速度。

#3


18  

I can't comment on how efficient this is, but here's a solution:

我无法评价它的效率有多高,但这里有一个解决方案:

applyToGivenRow = @(func, matrix) @(row) func(matrix(row, :))applyToRows = @(func, matrix) arrayfun(applyToGivenRow(func, matrix), 1:size(matrix,1))'% ExamplemyMx = [1 2 3; 4 5 6; 7 8 9];myFunc = @sum;applyToRows(myFunc, myMx)

#4


9  

Building on Alex's answer, here is a more generic function:

基于Alex的回答,这里有一个更通用的功能:

applyToGivenRow = @(func, matrix) @(row) func(matrix(row, :));newApplyToRows = @(func, matrix) arrayfun(applyToGivenRow(func, matrix), 1:size(matrix,1), 'UniformOutput', false)';takeAll = @(x) reshape([x{:}], size(x{1},2), size(x,1))';genericApplyToRows = @(func, matrix) takeAll(newApplyToRows(func, matrix));

Here is a comparison between the two functions:

以下是两个功能的比较:

>> % ExamplemyMx = [1 2 3; 4 5 6; 7 8 9];myFunc = @(x) [mean(x), std(x), sum(x), length(x)];>> genericApplyToRows(myFunc, myMx)ans =     2     1     6     3     5     1    15     3     8     1    24     3>> applyToRows(myFunc, myMx)??? Error using ==> arrayfunNon-scalar in Uniform output, at index 1, output 1.Set 'UniformOutput' to false.Error in ==> @(func,matrix)arrayfun(applyToGivenRow(func,matrix),1:size(matrix,1))'

#5


5  

For completeness/interest I'd like to add that matlab does have a function that allows you to operate on data per-row rather than per-element. It is called rowfun (http://www.mathworks.se/help/matlab/ref/rowfun.html), but the only "problem" is that it operates on tables (http://www.mathworks.se/help/matlab/ref/table.html) rather than matrices.

对于完整性/兴趣,我想补充的是,matlab确实有一个函数,它允许您按每一行而不是每个元素来操作。它被称为rowfun (http://www.mathworks.se/help/matlab/ref/rowfun.html),但唯一的“问题”是它对表(http://www.mathworks.se/help/matlab/ref/table.html)进行操作,而不是对矩阵进行操作。

#6


3  

Adding to the evolving nature of the answer to this question, starting with r2016b, MATLAB will implicitly expand singleton dimensions, removing the need for bsxfun in many cases.

从r2016b开始,MATLAB将隐式地扩展单例维度,在许多情况下消除了对bsxfun的需要,从而增加了这个问题的答案的演变性质。

From the r2016b release notes:

r2016b发行说明:

Implicit Expansion: Apply element-wise operations and functions to arrays with automatic expansion of dimensions of length 1

隐式展开:将元素操作和函数应用到长度为1的数组中

Implicit expansion is a generalization of scalar expansion. With scalar expansion, a scalar expands to be the same size as another array to facilitate element-wise operations. With implicit expansion, the element-wise operators and functions listed here can implicitly expand their inputs to be the same size, as long as the arrays have compatible sizes. Two arrays have compatible sizes if, for every dimension, the dimension sizes of the inputs are either the same or one of them is 1. See Compatible Array Sizes for Basic Operations and Array vs. Matrix Operations for more information.

内隐展开是标量展开的一般化。对于标量展开,标量扩展为与另一个数组相同的大小,以促进元素方面的操作。使用隐式展开,这里列出的元素操作符和函数可以隐式地将它们的输入扩展为相同的大小,只要数组具有兼容的大小。如果对于每个维度,输入的维度大小是相同的,或者其中一个是1,那么两个数组的大小是一致的。有关基本操作和数组与矩阵操作的更多信息,请参阅兼容数组大小。

Element-wise arithmetic operators — +, -, .*, .^, ./, .\Relational operators — <, <=, >, >=, ==, ~=Logical operators — &, |, xorBit-wise functions — bitand, bitor, bitxorElementary math functions — max, min, mod, rem, hypot, atan2, atan2d

For example, you can calculate the mean of each column in a matrix A, and then subtract the vector of mean values from each column with A - mean(A).

例如,你可以计算矩阵a中的每一列的均值,然后用a - mean(a)减去每一列的均值向量。

Previously, this functionality was available via the bsxfun function. It is now recommended that you replace most uses of bsxfun with direct calls to the functions and operators that support implicit expansion. Compared to using bsxfun, implicit expansion offers faster speed, better memory usage, and improved readability of code.

以前,这个功能可以通过bsxfun函数获得。现在建议您使用直接调用支持隐式扩展的函数和操作符来替代bsxfun的大多数用途。与使用bsxfun相比,隐式扩展提供了更快的速度、更好的内存使用和提高代码的可读性。

#7


1  

With recent versions of Matlab, you can use the Table data structure to your advantage. There's even a 'rowfun' operation but I found it easier just to do this:

使用Matlab的最新版本,您可以使用表数据结构来发挥优势。甚至还有一个“rowfun”手术,但我发现这样做更容易:

a = magic(6);incrementRow = cell2mat(cellfun(@(x) x+1,table2cell(table(a)),'UniformOutput',0))

or here's an older one I had that doesn't require tables, for older Matlab versions.

这里有一个旧的,不需要表格的,用旧的Matlab版本。

dataBinner = cell2mat(arrayfun(@(x) Binner(a(x,:),2)',1:size(a,1),'UniformOutput',0)')

#8


0  

The accepted answer seems to be to convert to cells first and then use cellfun to operate over all of the cells. I do not know the specific application, but in general I would think using bsxfun to operate over the matrix would be more efficient. Basically bsxfun applies an operation element-by-element across two arrays. So if you wanted to multiply each item in an n x 1 vector by each item in an m x 1 vector to get an n x m array, you could use:

公认的答案似乎是先转换成单元格,然后使用cellfun对所有单元格进行操作。我不知道具体的应用,但总的来说,我认为使用bsxfun操作矩阵会更有效。基本上,bsxfun在两个数组中逐个元素地应用操作。如果你想用一个n x 1向量中的每一项乘以一个m x 1向量中的每一项得到一个n x m数组,你可以用:

vec1 = [ stuff ];    % n x 1 vectorvec2 = [ stuff ];    $ m x 1 vectorresult = bsxfun('times', vec1.', vec2);

This will give you matrix called result wherein the (i,j) entry will be the ith element of vec1 multiplied by the jth element of vec2.

这会得到一个叫做result的矩阵,其中(i,j)项是向量1的第i个元素乘以向量2的第j个元素。

You can use bsxfun for all sorts of built-in functions, and you can declare your own. The documentation has a list of many built-in functions, but basically you can name any function that accepts two arrays (vector or matrix) as arguments and get it to work.

您可以为各种内置函数使用bsxfun,您可以声明自己的功能。该文档有许多内置函数的列表,但是基本上您可以命名任何接受两个数组(向量或矩阵)作为参数的函数并使其工作。

#9


0  

None of the above answers worked "out of the box" for me, however, the following function, obtained by copying the ideas of the other answers works:

以上的答案对我来说都不是“开箱即用”的,但是,通过复制其他答案的想法获得的以下功能是有效的:

apply_func_2_cols = @(f,M) cell2mat(cellfun(f,num2cell(M,1), 'UniformOutput',0));

It takes a function f and applies it to every column of the matrix M.

它取一个函数f并把它应用到矩阵M的每一列。

So for example:

举个例子:

f = @(v) [0 1;1 0]*v + [0 0.1]';apply_func_2_cols(f,[0 0 1 1;0 1 0 1]) ans =   0.00000   1.00000   0.00000   1.00000   0.10000   0.10000   1.10000   1.10000

#10


-1  

Stumbled upon this question/answer while seeking how to compute the row sums of a matrix.

在寻找如何计算矩阵的行和时,偶然发现了这个问题/答案。

I would just like to add that Matlab's SUM function actually has support for summing for a given dimension, i.e a standard matrix with two dimensions.

我想补充的是Matlab的和函数实际上支持对给定维度I求和。一个二维的标准矩阵。

So to calculate the column sums do:

因此,计算列和的方法是:

colsum = sum(M) % or sum(M, 1)

and for the row sums, simply do

对于行和,只要做

rowsum = sum(M, 2)

My bet is that this is faster than both programming a for loop and converting to cells :)

我敢打赌,这比编写for循环和转换为cell都要快:)

All this can be found in the matlab help for SUM.

所有这些都可以在matlab帮助下求和。

#11


-1  

if you know the length of your rows you can make something like this:

如果你知道行的长度,你可以这样做:

a=rand(9,3);b=rand(9,3); arrayfun(@(x1,x2,y1,y2,z1,z2) line([x1,x2],[y1,y2],[z1,z2]) , a(:,1),b(:,1),a(:,2),b(:,2),a(:,3),b(:,3) )