2010-02-21 207 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 
相關問題