我怎样才能应用一个函数到matrix的每一行/列在MATLAB中?

你可以通过例如v + 1来向vector中的每个项目应用一个函数,或者你可以使用函数arrayfun 。 我怎样才能做到这一点matrix的每一行/列而不使用for循环?

sumprod这样的内置操作已经可以跨行或列操作了,所以你可以重构你正在使用的函数来利用它。

如果这不是一个可行的select,一种方法是使用mat2cellnum2cell将行或列收集到单元格中,然后使用cellfun操作所得到的单元arrays。

作为一个例子,假设你想对matrixM的列进行求和。 你可以简单地使用sum来做到这一点:

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

这里是你如何使用更复杂的num2cell / cellfun选项来做到这一点:

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

你可能想要更晦涩的Matlab函数bsxfun 。 从Matlab文档中,bsxfun“将由函数handle fun指定的逐个元素的二进制操作应用于数组A和B,并启用单例扩展。

上面提到的@gnovice和sum和其他基本函数已经在第一个非单实体维度上进行了操作(即,如果有多行,那么行,如果只有一行,则列;或者如果较低维度都具有大小== 1 )。 但是,bsxfun适用于任何函数,包括(特别是)用户定义的函数。

例如,假设您有一个matrixA和一个行向量BEg,假设:

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

你想要一个函数power_by_col,它返回一个向量C中的所有元素到B的对应列的权力。

从上面的例子中,C是一个3×3的matrix:

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

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

你可以使用repmat来实现这个蛮力的方式:

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

或者你可以用bsxfun这个优雅的方式,在内部处理repmat步骤:

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

所以bsxfun为您节省了一些步骤(您不需要明确计算A的尺寸)。 然而,在我的一些非正式testing中,事实certificate,如果要应用的function(如上面的功率函数)很简单,repmat的速度大概是它的两倍。 所以你需要select你是否想要简单或速度。

我不能评论这是多高效,但这里有一个解决scheme:

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

基于Alex的回答 ,这是一个更通用的function:

 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)); 

这两个函数之间的比较:

 >> % Example myMx = [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 ==> arrayfun Non-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))' 

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

为了回答这个问题,从r2016b开始,MATLAB将隐含地扩展单例尺寸,在很多情况下不需要bsxfun

从r2016b发行说明 :

隐式扩展:将元素操作和函数应用于具有长度为1的维度的自动扩展的数组

隐式扩展是标量扩展的泛化。 通过标量扩展,标量扩展为与另一个数组相同的大小,以便于按元素操作。 通过隐式扩展,只要数组具有兼容的大小,这里列出的按元素的操作符和函数就可以隐式地扩展它们的input大小。 如果对于每个维度,input的维度大小相同或其中之一为1,则两个arrays具有兼容的大小。有关更多信息,请参阅基本操作的兼容arrays大小以及arrays与matrix操作。

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

例如,您可以计算matrixA中每列的平均值,然后用A – 均值(A)从每列中减去平均值的向量。

以前,这个function可以通过bsxfun函数获得。 现在build议您将bsxfun的大部分用法直接调用到支持隐式扩展的函数和运算符。 与使用bsxfun相比,隐式扩展提供了更快的速度,更好的内存使用,并提高了代码的可读性。

使用最新版本的Matlab,您可以使用Table数据结构来获得优势。 甚至有一个“rowfun”操作,但我发现这样做更容易:

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

或者这是一个旧的,我不需要表格,旧的Matlab版本。

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

接受的答案似乎是先转换为单元格,然后使用cellfun来操作所有的单元格。 我不知道具体的应用程序,但总的来说,我认为使用bsxfun在matrix上运行会更有效率。 基本上bsxfun在两个数组之间应用一个元素的操作。 所以,如果你想乘以一个nxm向量中的每个项目乘以一个nxm向量中的每个项目来获得一个nxm数组,你可以使用:

 vec1 = [ stuff ]; % nx 1 vector vec2 = [ stuff ]; $ mx 1 vector result = bsxfun('times', vec1.', vec2); 

这将给你称为resultmatrix,其中(i,j)项将是vec1的第i个元素乘以vec1的第j个元素。

你可以使用bsxfun来实现各种内置函数,你可以声明你自己的函数。 该文档有许多内置函数的列表,但基本上你可以命名任何接受两个数组(vector或matrix)作为参数的函数并使其工作。

上面的答案都不是“开箱即用”的,但是,通过复制其他答案的思想获得的以下function是可行的:

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

它取一个函数f并将其应用于matrixM每一列。

举个例子:

 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 

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

我只想补充一点,Matlab的SUM函数实际上支持对一个给定的维度进行求和,也就是具有两个维度的标准matrix。

所以要计算列的总和呢:

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

对于行数,简单的做

 rowsum = sum(M, 2) 

我敢打赌,这是比编程循环和转换为单元格:)

所有这些都可以在SUM的matlab帮助中find。

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

 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) )