乱数の行列を含むセルがありますa = {[300*20],....,[300*20]};
。同じ形式の別のセルを持っていb
ます。nan
a
cellfun
セルをループして、基本的に用語をienan
に等しくするために使用したい。0
a(b)=0
ありがとう、j
乱数の行列を含むセルがありますa = {[300*20],....,[300*20]};
。同じ形式の別のセルを持っていb
ます。nan
a
cellfun
セルをループして、基本的に用語をienan
に等しくするために使用したい。0
a(b)=0
ありがとう、j
NaN をゼロに置き換える関数を定義できます。
function a = nan2zero(a)
a(isnan(a)) = 0;
次に、cellfun
この関数をセル配列に適用するために使用できます。
a0 = cellfun(@nan2zero, a, 'UniformOutput', 0)
そうすれば、マトリックスも必要ありませんb
。
まず、@s.bandara にチェックマークを付ける必要があります。これが最初の正解であり、cellfun
(要求どおり) 使用されたからです。この答えにそれを与えないでください。この回答の目的は、追加の分析を提供することです。
この問題に対するいくつかの可能なアプローチの効率を調べてみようと思いました。
最初のアプローチは、@s.bandara によって提唱されたものです。
2 番目のアプローチは @s.bandara が提唱するものと似ていますb
が、. 理論的には、関数内には何も割り当てられていないため、この方法の方が高速である可能性があるため、「By Ref」として処理する必要があります。nan
0
isnan
b
cellfun は明示的なループよりも遅いことが多いcellfun
ため、3 番目のアプローチではループを使用して を回避します。
簡単な速度テストの結果は次のとおりです。
Elapsed time is 3.882972 seconds. %# First approach (a, isnan, and cellfun, eg @s.bandara)
Elapsed time is 3.391190 seconds. %# Second approach (a, b, and cellfun)
Elapsed time is 3.041992 seconds. %# Third approach (loop-based solution)
言い換えると、b
を使用するのではなく、 を渡すことで (わずかな) 節約ができisnan
ます。また、 ではなくループを使用することで、さらに (小さな) 節約ができますcellfun
。しかし、私はそれで眠りを失うことはありません。シミュレーションの結果は、指定された入力に固有のものであることを忘れないでください。
これらの結果は、いくつかの実行で一貫していたことに注意してください。各メソッドで多くのループが発生しましたが、これを行うためにtic
とを使用しました。toc
本当に徹底したいのであればtimeit
、FEX から使用する必要があります。興味のある方は、3 つのメソッドのコードを次に示します。
%# Build some example matrices
T = 1000; N = 100; Q = 50; M = 100;
a = cell(1, Q); b = cell(1, Q);
for q = 1:Q
a{q} = randn(T, N);
b{q} = logical(randi(2, T, N) - 1);
a{q}(b{q}) = nan;
end
%# Solution using a, isnan, and cellfun (@s.bandara solution)
tic
for m = 1:M
Soln2 = cellfun(@f1, a, 'UniformOutput', 0);
end
toc
%# Solution using a, b, and cellfun
tic
for m = 1:M
Soln1 = cellfun(@f2, a, b, 'UniformOutput', 0);
end
toc
%# Solution using a loop to avoid cellfun
tic
for m = 1:M
Soln3 = cell(1, Q);
for q = 1:Q
Soln3{q} = a{q};
Soln3{q}(b{q}) = 0;
end
end
toc
%# Solution proposed by @EitanT
[K, N] = size(a{1});
tic
for m = 1:M
a0 = [a{:}]; %// Concatenate matrices along the 2nd dimension
a0(isnan(a0)) = 0; %// Replace NaNs with zeroes
Soln4 = mat2cell(a0, K, N * ones(size(a)));
end
toc
どこ:
function x1 = f1(x1)
x1(isnan(x1)) = 0;
と:
function x1 = f2(x1, x2)
x1(x2) = 0;
更新: 4 番目のアプローチが @EitanT によって提案されました。この方法では、行列の cell 配列を 1 つの大きな行列に連結し、その大きな行列に対して演算を実行してから、必要に応じてそれを cell 配列に変換します。この手順のコードを上記のテスト ルーチンに追加しました。私のテスト コードで指定された入力、つまりT = 1000
、N = 100
、Q = 50
、およびM = 100
の場合、実行時間は次のようになります。
Elapsed time is 3.916690 seconds. %# @s.bandara
Elapsed time is 3.362319 seconds. %# a, b, and cellfun
Elapsed time is 2.906029 seconds. %# loop-based solution
Elapsed time is 4.986837 seconds. %# @EitanT
@EitanT のアプローチが最良の結果をもたらすと思っていたので、これには少し驚きました。紙の上では、それは非常に理にかなっているように見えます。もちろん、入力パラメーターをいじって、さまざまなソリューションに有利な特定の設定を見つけることができることに注意してください。たとえば、行列が小さいが、それらの数が多い場合、@EitanT のアプローチはうまくT = 10
機能N = 5
しQ = 500
ますM = 100
。
Elapsed time is 0.362377 seconds. %# @s.bandara
Elapsed time is 0.299595 seconds. %# a, b, and cellfun
Elapsed time is 0.352112 seconds. %# loop-based solution
Elapsed time is 0.030150 seconds. %# @EitanT
ここでは @EitanT のアプローチが優勢です。
OP で示された問題の規模については、通常、ループ ベースのソリューションが最高のパフォーマンスを発揮することがわかりました。ただし、@EitanT のソリューションなど、一部Q
のQ = 5
ソリューションでは優位に立つことができました。
うーん。
セル配列の内容の性質を考えると、さらに高速な解決策が存在する可能性があります。セルデータを単一の行列に変換し、ベクトルインデックスを使用して、ループNaN
を必要とせずに、その中のすべての値を一度に置き換えることができます。cellfun
a0 = [a{:}]; %// Concatenate matrices along the 2nd dimension
a0(isnan(a0)) = 0; %// Replace NaNs with zeroes
セル配列に変換し直したい場合は、それで問題ありません。
[M, N] = size(a{1});
mat2cell(a0, M, N * ones(size(a)))
PS
可能であれば、セル配列の代わりに3Dマトリックスを使用します。ベクトル化された操作は、通常、MATLABでははるかに高速です。