2010-02-21 69 views

回答

66

许多内置操作如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 
+16

我将测试该方法的性能针对简单for循环任何特定的情况下,这可能会更快然后转换矩阵单元阵列。使用tic/tac wrap来测试。 – yuk 2010-02-21 23:13:03

+5

@yuk:我认为你的意思是“tic/toc”。 ;) – gnovice 2010-02-22 05:43:43

+2

哎呀,当然!只是在滴答...... :) – yuk 2010-02-22 15:05:29

-1

就这个问题/答案迷迷糊糊的,同时寻求如何计算矩阵的行和。

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

所以计算列总和做到:

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

与该行资金,根本就

rowsum = sum(M, 2) 

我敢打赌,这是快于既为循环编程并转换到细胞:)

所有这一切都可以在MATLAB的MATLAB帮助中找到。

+7

在这个问题的原始答案的第一句中提到了沿给定维度应用SUM的能力。然后,答案继续解决选择维度的功能尚未内置到该功能的情况。不过,你说得对,使用内置的尺寸选择选项 - 当它们可用时 - 几乎总是比for循环或转换为单元更快。 – cjh 2012-09-22 15:54:40

+0

但是,上面的答案是真的,因为我不需要所有的幻想,所以我只想分享和保存其他人,需要寻找简单的解决方案。 – nover 2012-10-05 13:05:18

18

我不能就如何高效,这是的,但在这里评论的一个解决方案:

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

给出一个更通用的答案[这里](http://stackoverflow.com/a/15971182/376454)。 – Wok 2013-04-12 12:28:31

9

大厦Alex's answer,这里是一个比较通用的功能:

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

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

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

例如,假设你有一个矩阵A和行向量求,让我们说:

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

你想要的功能power_by_col它在一个载体下,在所有元素返回的力量B.

从上面的例子中的相应列中,C是一个3×3矩阵:

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的尺寸)。然而,在我的一些非正式测试中,事实证明,如果要应用的功能(如上面的功率函数)很简单,repmat的速度大概是它的两倍。所以你需要选择你是想要简单还是速度。

0

接受的答案似乎是首先转换为单元格,然后使用cellfun来操作所有单元格。我不知道具体的应用,但总的来说,我认为使用bsxfun在矩阵上运行会更有效率。基本上bsxfun跨两个数组应用一个元素操作。所以,如果你想通过每个项目在m x 1向量乘在n x 1向量中的每个项目获得的n x 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,并且您可以声明自己的函数。该文档包含许多内置函数的列表,但基本上可以将任何接受两个数组(矢量或矩阵)的函数命名为参数并使其起作用。

-1

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

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

对于看到这个答案的人:这不是做这件事的方法!这不是在MATLAB中做任何事情的方法! – 2016-08-10 12:12:06

1

使用最新版本的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)') 
3

添加到答案的性质演变到这个问题,开始r2016b,MATLAB会隐扩大单维度,在许多情况下不再需要为bsxfun

r2016b release notes

隐扩展:应用逐元素的操作和功能与长度的尺寸自动膨胀到阵列1

隐膨胀是标量膨胀的概括。通过标量扩展,标量扩展为与另一个 数组相同的尺寸,以便于元素操作。通过隐式扩展,只要数组具有 兼容大小,这里列出的按元素运算符和函数就可以隐式地将其输入扩展为相同大小。如果对于每个维度,输入的维度大小相同,或者其中一个维度大小为 ,则两个阵列具有兼容的大小。有关更多信息,请参阅基本操作的兼容阵列大小和 阵列与矩阵运算。

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 

例如,可以计算各列的均值以矩阵A, 然后从每一列与减去平均值的矢量A - 平均值(A)。

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

0

上述答案的工作“开箱即用”对我来说,但是,下面的函数,通过复制其他答案的想法得到工作:

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 
相关问题