Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I apply a function to every row/column of a matrix in MATLAB?

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?

like image 776
FurtiveFelon Avatar asked Feb 21 '10 19:02

FurtiveFelon


People also ask

How do I apply a function to each row in MATLAB?

B = rowfun( func , A ) applies the function func to each row of the table or timetable A and returns the results in the table or timetable B .

How do you apply a whole column in MATLAB?

If you want to access all of the rows or columns, use the colon operator by itself. For example, return the entire third column of A . In general, you can use indexing to access elements of any array in MATLAB regardless of its data type or dimensions.

How do I add all values to a row in MATLAB?

S = sum( A , 'all' ) computes the sum of all elements of A . This syntax is valid for MATLAB® versions R2018b and later. S = sum( A , dim ) returns the sum along dimension dim . For example, if A is a matrix, then sum(A,2) is a column vector containing the sum of each row.


3 Answers

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.

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.

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

M = magic(10);           %# A 10-by-10 matrix
columnSums = 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:

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
like image 116
gnovice Avatar answered Oct 20 '22 21:10

gnovice


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."

@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.

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

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.

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

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:

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:

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.

like image 24
Daniel Golden Avatar answered Oct 20 '22 22:10

Daniel Golden


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

% Example
myMx = [1 2 3; 4 5 6; 7 8 9];
myFunc = @sum;

applyToRows(myFunc, myMx)
like image 23
Alex Avatar answered Oct 20 '22 22:10

Alex