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

发布于 2024-08-22 04:59:27 字数 110 浏览 7 评论 0原文

您可以将函数应用于向量中的每个项目,例如,v + 1,或者您可以使用函数arrayfun。如何在不使用 for 循环的情况下对矩阵的每一行/列执行此操作?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

可爱暴击 2024-08-29 04:59:28

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

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.

羁拥 2024-08-29 04:59:28

除了这个问题答案的不断演变之外,从 r2016b 开始,MATLAB 将隐式扩展单例维度,在许多情况下不再需要 bsxfun

来自 r2016b 发行说明

隐式扩展:将逐元素运算和函数应用于数组,并自动扩展长度为 1 的维度

隐式扩展是标量扩展的推广。和
标量扩展,一个标量扩展为与另一个标量相同的大小
数组以方便按元素操作。通过隐式展开,
此处列出的逐元素运算符和函数可以隐式
将它们的输入扩展为相同的大小,只要数组具有
兼容尺寸。两个数组具有兼容的大小,如果对于每个
维度,输入的维度大小要么相同,要么
其中之一是 1. 请参阅基本操作的兼容数组大小和
数组与矩阵运算了解更多信息。

逐元素算术运算符 — +、-、.*、.^、./、.\

关系运算符 — <、<=、>、>=、==、~=

逻辑运算符 — &、|、异或

按位函数 — bitand、bitor、bitxor

基本数学函数 — max、min、mod、rem、hypot、atan2、atan2d

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

以前,此功能可通过 bsxfun 函数使用。
现在建议您将 bsxfun 的大部分用法替换为直接
对支持隐式扩展的函数和运算符的调用。
与使用 bsxfun 相比,隐式扩展提供更快的速度,
更好的内存使用,并提高代码的可读性。

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.

From the r2016b release notes:

Implicit Expansion: Apply element-wise operations and functions to arrays with automatic expansion of dimensions of length 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.

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

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

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.

牛↙奶布丁 2024-08-29 04:59:28

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

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

它采用函数 f 并将其应用于每一列矩阵M

例如:

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

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.

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
戈亓 2024-08-29 04:59:28

使用最新版本的 Matlab,您可以使用表数据结构来发挥自己的优势。甚至还有一个“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)')

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:

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.

dataBinner = cell2mat(arrayfun(@(x) Binner(a(x,:),2)',1:size(a,1),'UniformOutput',0)')
戏剧牡丹亭 2024-08-29 04:59:28

接受的答案似乎是首先转换为单元格,然后使用 cellfun 对所有单元格进行操作。我不知道具体的应用,但一般来说我会认为使用 bsxfun 对矩阵进行操作会更高效。基本上,bsxfun 在两个数组中逐个元素地应用操作。因此,如果您想将 nx 1 向量中的每个项目乘以 mx 1 向量中的每个项目以获得 nx m 数组,您可以可以使用:

vec1 = [ stuff ];    % n x 1 vector
vec2 = [ stuff ];    % m x 1 vector
result = bsxfun('times', vec1.', vec2);

这将为您提供名为 result 的矩阵,其中 (i, j) 条目将是 vec1 的第 i 个元素乘以 vec2< 的第 j 个元素/代码>。

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

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:

vec1 = [ stuff ];    % n x 1 vector
vec2 = [ stuff ];    % m x 1 vector
result = 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.

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.

宛菡 2024-08-29 04:59:28

我喜欢 splitapply,它允许使用 splitapply(fun,A,1:size(A,2))< 将函数应用于 A 的列/代码>。

例如,

A = magic(5);
B = splitapply(@(x) x+1, A, 1:size(A,2));
C = splitapply(@std,  A, 1:size(A,2));

要将函数应用于行,您可以使用
splitapply(fun, A', 1:size(A,1))';

(此解决方案的来源是 此处。)

I like splitapply, which allows a function to be applied to the columns of A using splitapply(fun,A,1:size(A,2)).

For example

A = magic(5);
B = splitapply(@(x) x+1, A, 1:size(A,2));
C = splitapply(@std,  A, 1:size(A,2));

To apply the function to the rows, you could use
splitapply(fun, A', 1:size(A,1))';

(My source for this solution is here.)

丘比特射中我 2024-08-29 04:59:28

您仍然可以使用 arrayfun 。

% customed function
myfun=@(x) sum(x)

M=[1 2 3; 4 5 6]

% by column
arrayfun(@(c) myfun(M(:,c)),1:size(M,2))

% by row
arrayfun(@(r) myfun(M(r,:)),1:size(M,1))

但是,按列时 splitapply 会更短。

% by column
splitapply(myfun,M,1:size(M,2))

You can still use arrayfun too.

% customed function
myfun=@(x) sum(x)

M=[1 2 3; 4 5 6]

% by column
arrayfun(@(c) myfun(M(:,c)),1:size(M,2))

% by row
arrayfun(@(r) myfun(M(r,:)),1:size(M,1))

But, splitapply is shorter when by column.

% by column
splitapply(myfun,M,1:size(M,2))
半衬遮猫 2024-08-29 04:59:28

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

我想补充一点,Matlab 的 SUM 函数实际上支持给定维度(即二维标准矩阵)求和。

因此,要计算列总和,只需执行以下操作:

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

对于行总和,只需执行以下操作:

rowsum = sum(M, 2)

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

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

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.

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

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

ゞ花落谁相伴 2024-08-29 04:59:28

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

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

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) )
半城柳色半声笛 2024-08-29 04:59:27

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

如果这不是一个可行的选择,一种方法是使用 mat2cellnum2cell,然后使用 cellfun 对生成的元胞数组进行操作。

举个例子,假设您想要对矩阵 M 的列求和。您只需使用 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

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
泪意 2024-08-29 04:59:27

您可能需要更晦涩的 Matlab 函数 bsxfun。根据 Matlab 文档,bsxfun“将函数句柄 fun 指定的逐元素二元运算应用于数组 A 和 B,并启用单例扩展。”

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

例如,假设您有一个矩阵 A 和一个行向量 BEg,假设:

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

您需要一个函数 power_by_col,它在向量 C 中返回 A 中的所有元素的 B 相应列的幂。

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

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以优雅的方式执行此操作,bsxfun在内部处理repmat步骤:

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

因此bsxfun为您节省了一些步骤(您不需要需要显式计算 A) 的尺寸。然而,在我的一些非正式测试中,结果表明,如果要应用的函数(如上面的幂函数)很简单,repmat 的速度大约是原来的两倍。因此,您需要选择是想要简单性还是速度。

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.

你丑哭了我 2024-08-29 04:59:27

我无法评论这有多高效,但这里有一个解决方案:

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)

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)
踏雪无痕 2024-08-29 04:59:27

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

这​​是两个函数之间的比较:

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

Building on Alex's answer, here is a more generic 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));

Here is a comparison between the two functions:

>> % 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))'
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文