たとえば、と発声することで、ベクター内のすべてのアイテムに関数を適用できます。また、関数をv + 1
使用することもできますarrayfun
。forループを使用せずに、行列のすべての行/列に対してどのように実行できますか?
たとえば、と発声することで、ベクター内のすべてのアイテムに関数を適用できます。また、関数をv + 1
使用することもできますarrayfun
。forループを使用せずに、行列のすべての行/列に対してどのように実行できますか?
回答:
多くのような操作を内蔵sum
し、prod
すでにあなたがこれを利用するために適用されている機能をリファクタリングすることができるかもしれので、行または列にわたって動作することができます。
それは実行可能な選択肢ではないなら、それを行うための一つの方法は、使用して細胞内に行または列を収集することであるmat2cell
かnum2cell
、そして使用し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
true = false
が有効なステートメントである言語では、あなたがそれを行うことができる方法があると私は確信しています(:
sum(M, 1)
。初心者は、sum
この方法を任意のサイズのマトリックスに使用できると考えて、マトリックスの1日がになると困惑するかもしれません1-by-n
。
より不明瞭なMatlab関数bsxfunが必要な場合があります。Matlabドキュメンテーションから、bsxfunは、「関数ハンドルfunで指定された要素ごとのバイナリ演算を、シングルトン展開が有効になっている配列AおよびBに適用します。」
上記の@gnoviceは、合計およびその他の基本的な関数が最初の1でない次元(つまり、複数の行がある場合は行、1行しかない場合は列、または低い次元がすべてsize == 1の場合は高い次元)で動作することを述べました。 )。ただし、bsxfunは(特に)ユーザー定義関数を含むすべての関数で機能します。
たとえば、行列Aと行ベクトルBEgがあるとしましょう。
A = [1 2 3;
4 5 6;
7 8 9]
B = [0 1 2]
Aのすべての要素をBの対応する列の累乗でベクトルCに返す関数power_by_colが必要です。
上記の例から、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)
または、内部でrepmatステップを処理するbsxfunを使用して上品な方法でこれを行うことができます。
C = bsxfun(@(x,y) x.^y, A, B)
そのため、bsxfunはいくつかの手順を節約します(Aの次元を明示的に計算する必要はありません)。ただし、私の非公式のテストでは、適用する関数(上記の私のべき関数のように)が単純な場合、repmatはおよそ2倍高速であることが判明しています。したがって、シンプルにするかスピードにするかを選択する必要があります。
これがいかに効率的であるかについてコメントすることはできませんが、これが解決策です:
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)
アレックスの答えに基づいて、これはより一般的な関数です:
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));
2つの関数の比較を次に示します。
>> % 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には要素ごとではなく行ごとにデータを操作できる関数があることを付け加えておきます。これはrowfun
(http://www.mathworks.se/help/matlab/ref/rowfun.html)と呼ばれますが、唯一の「問題」は、それがテーブル(http://www.mathworks.se/help/ マトリックスではなく、matlab / ref / table.html)。
この質問への答えの進化する性質に加えて、r2016b以降、MATLABは暗黙的にシングルトンの次元を拡張しbsxfun
、多くの場合で必要性を排除します。
暗黙的な拡張:長さ1の次元の自動拡張を使用して、要素ごとの演算と関数を配列に適用します。
暗黙的な拡張は、スカラー拡張の一般化です。スカラー拡張を使用すると、スカラーは別の配列と同じサイズに拡張され、要素ごとの操作が容易になります。暗黙的な展開では、配列に互換性のあるサイズがある限り、ここにリストされている要素ごとの演算子と関数は、入力を暗黙的に同じサイズに展開できます。すべての次元について、入力の次元サイズが同じか、1つが1の場合、2つの配列は互換性のあるサイズを持ちます。
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-mean(A)を使用して各列から平均値のベクトルを減算できます。
以前は、この機能はbsxfun関数を介して利用できました。現在、bsxfunのほとんどの使用を、暗黙の拡張をサポートする関数および演算子の直接呼び出しに置き換えることをお勧めします。bsxfunを使用する場合と比較して、暗黙的な拡張により、速度が速くなり、メモリ使用量が増え、コードの可読性が向上します。
上記の回答はどれも「そのまま」機能しませんでしたが、他の回答のアイデアをコピーして得られた次の機能は機能します。
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
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)')
受け入れられた答えは、最初にセルに変換してからcellfun
、すべてのセルを操作するために使用することです。特定のアプリケーションはわかりませんが、一般的にはbsxfun
、マトリックスを操作するために使用する方が効率的だと思います。基本的bsxfun
に、2つの配列にわたって要素ごとに操作を適用します。したがって、配列を取得するn x 1
ためにm 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)エントリがのj番目の要素でvec1
乗算されたi番目の要素となると呼ばれる行列が得られますvec2
。
bsxfun
あらゆる種類の組み込み関数に使用でき、独自の関数を宣言できます。ドキュメントには多くの組み込み関数のリストがありますが、基本的には2つの配列(ベクトルまたは行列)を引数として受け入れる任意の関数に名前を付けて機能させることができます。
行列の行の合計を計算する方法を模索しているときに、この質問/回答に遭遇しました。
MatlabのSUM関数が、特定の次元、つまり2次元の標準行列の合計を実際にサポートしていることを付け加えておきます。
したがって、列の合計を計算するには、次のようにします。
colsum = sum(M) % or sum(M, 1)
行の合計については、単に
rowsum = sum(M, 2)
私の賭けは、これがforループのプログラミングとセルへの変換の両方よりも速いということです:)
これはすべて、SUMのMATLABヘルプで確認できます。
行の長さがわかっている場合は、次のようにすることができます。
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) )