MATLABのマップ関数?


100

MATLABにMap関数がないことに少し驚いたので、それがないと生きていけないので、自分でハッキングしました。より良いバージョンはありますか?不足している、MATLAB用のやや標準的な関数型プログラミングライブラリはありますか?

function results = map(f,list)
% why doesn't MATLAB have a Map function?
results = zeros(1,length(list));
for k = 1:length(list)
    results(1,k) = f(list(k));
end

end

使い方は例えば

map( @(x)x^2,1:10)

12
他の言語からMatlabへのレッスン#1:forループを使用しないでください。これらは、ベクトル化されたソリューションよりも数桁遅いです。
CookieOfFortune 2009年

15
JITの導入により、forループは以前のようなペナルティを受けません。
MatlabDoug 2009年

@CookieOfFortuneそれはもう本当ではないと思います...
Ander Biguri '28

2
@AnderBiguri私は彼らがいくつかの改善を加えたと思いますが、それでもまだずっと遅いです。
CookieOfFortune

機能的なライブラリファイル交換でありmapfoldl(またとして知られているreduce)、 select(別名filter)、およびその他の必要不可欠なグッズ。推奨(Matlabを使用する必要がある場合)。
Ahmed Fasih、2015年

回答:


133

短い答え:組み込み関数は、数値配列に対して関数が実行するarrayfunことを正確に実行しmapます。

>> y = arrayfun(@(x) x^2, 1:10)
y =

     1     4     9    16    25    36    49    64    81   100

同様に動作する他の2つの組み込み関数があります:(cellfunセル配列の要素で動作する)およびstructfun(構造体の各フィールドで動作する)。

ただし、ベクトル化を利用する場合、特に要素ごとの算術演算子を使用する場合、これらの関数はしばしば必要ありません。あなたが与えた例では、ベクトル化されたソリューションは次のようになります:

>> x = 1:10;
>> y = x.^2
y =

     1     4     9    16    25    36    49    64    81   100

一部の操作は要素全体で自動的に動作します(スカラー値をベクトルに追加するなど)一方で、他の演算子には要素ごとの操作(.演算子の前にaで示される)のための特別な構文があります。組み込みMATLABの関数の多くは、(多くの場合など、所定の寸法に適用される要素単位操作を使用してベクトルと行列引数で動作するように設計されているsummean、例えば)、したがってマップ機能を必要としません。

まとめると、配列内の各要素を二乗するいくつかの方法があります。

x = 1:10;       % Sample array
f = @(x) x.^2;  % Anonymous function that squares each element of its input

% Option #1:
y = x.^2;  % Use the element-wise power operator

% Option #2:
y = f(x);  % Pass a vector to f

% Option #3:
y = arrayfun(f, x);  % Pass each element to f separately

もちろん、そのような単純な操作では、オプション#1が最も賢明(かつ効率的)な選択肢です。


2
オプション1の方が単純であるだけでなく高速でもあることに注意してください(オプション3と比較すると、2は1と非常に類似しています)。
Diederick C. Niehorster 2014年

10

ベクトル演算と要素ごとの演算に加えてcellfun、セル配列に対する関数のマッピングもあります。例えば:

cellfun(@upper, {'a', 'b', 'c'}, 'UniformOutput',false)
ans = 
    'A'    'B'    'C'

'UniformOutput'がtrue(または指定されていない)の場合、セル配列の次元に従って結果を連結しようとするため、

cellfun(@upper, {'a', 'b', 'c'})
ans =
ABC

2

Matlabのベクトル化を使用したかなり単純なソリューションは次のようになります。

a = [ 10 20 30 40 50 ]; % the array with the original values
b = [ 10 8 6 4 2 ]; % the mapping array
c = zeros( 1, 10 ); % your target array

今、タイプして

c( b ) = a

戻り値

c = 0    50     0    40     0    30     0    20     0    10

c(b)は、bで指定されたインデックスにcの要素を持つサイズ5のベクトルへの参照です。この参照ベクトルに値を割り当てると、c(b)にはcの値への参照が含まれ、コピーは含まれないため、cの元の値は上書きされます。


1

必要な結果が関数の配列である場合、組み込みのarrayfunは機能しないようです。例:map(@(x)[xx ^ 2 x ^ 3]、1:10)

以下のわずかな変更はこの作業をより良くします:

function results = map(f,list)
% why doesn't MATLAB have a Map function?
for k = 1:length(list)
    if (k==1)
        r1=f(list(k));
        results = zeros(length(r1),length(list));
        results(:,k)=r1;
    else
        results(:,k) = f(list(k));

    end;
end;
end

5
ARRAYFUNはあなたの例で機能します..., 'UniformOutput', false);。配列を含むセル配列出力を作成するために入力引数を含める必要があり、それをフォーマットして任意の非セル配列に結合します。
gnovice 2012

0

matlabにマップ関数が組み込まれていない場合は、効率を考慮している可能性があります。実装では、ループを使用してリストの要素を反復処理します。リストの要素は、通常、MATLABの世界では嫌われています。ほとんどの組み込みのMATLAB関数は「ベクトル化」されています。つまり、配列全体で関数を呼び出す方が、自分で反復して各要素の関数を呼び出すよりも効率的です。

つまり、これ


a = 1:10;
a.^2

これよりずっと速い


a = 1:10;
map(@(x)x^2, a)

マップの定義を想定しています。


2
彼のポイントは、彼が必ずしもループすることを望んでいたのではなく、その結果として、提供された関数を提供された配列の対応する要素に適用した結果の配列を持つように指定されることでした。私は多くのmatlabを知りませんが、arrayfunがうまくいくようです。

1
ほとんどの組み込みMatlab関数と演算子はすでにそれを実行しています。これらは入力配列の各要素を操作し、対応する結果の配列を返します。
Dima

0

map値のリストに適用されるスカラー関数は各値に適用されるため、と同様に機能するため、必要はありませんmap。ちょうど試して

l = 1:10
f = @(x) x + 1

f(l)

あなたの特定のケースでは、あなたは書くことさえできます

l.^2

9
-1:実際にはそうではありません。Matlabには、スカラー関数を指定できるほど強力な型システムがありません。fはベクトルで呼び出され、例では単一のベクトル加算が実行されます。これを確認するには、コードサンプルをプロファイリングします(コードを実行する前に「プロファイルオン」、その後に「プロファイルオフレポート」)。fへの呼び出しが1つあることがわかります。
Fooz氏、2009年

-1

前の回答で説明したようにソリューションをベクトル化することは、おそらく速度を上げるための最良のソリューションです。ベクトル化も非常にMatlabyで、気分が良いです。

これで、MatlabにはMapコンテナクラスが追加されました。

http://www.mathworks.com/help/matlab/map-containers.htmlを参照してください


Opはcellfun、ハッシュテーブルやキーと値のペアではなく、高次関数、つまり、その他について話している。
Ahmed Fasih、2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.