何千回も実行する必要があるため、NaNのない行のインデックスを可能な限り最速で見つけたいと思います。これまで、次の2つのアプローチを試しました。
find(~isnan(sum(data, 2)));
find(all(~isnan(data), 2));
これをスピードアップする賢い方法はありますか、それともこれが可能な限り最高ですか?データマトリックスの次元は通常、数千×数百です。
何千回も実行する必要があるため、NaNのない行のインデックスを可能な限り最速で見つけたいと思います。これまで、次の2つのアプローチを試しました。
find(~isnan(sum(data, 2)));
find(all(~isnan(data), 2));
これをスピードアップする賢い方法はありますか、それともこれが可能な限り最高ですか?データマトリックスの次元は通常、数千×数百です。
編集: 行列の乗算は合計よりも高速になる可能性があるため、500 x 500要素を超える行列の操作はほぼ2倍高速になります(私のMatlab 2012aマシンの場合)。だから私の解決策は:
find(~isnan(data*zeros(size(data,2),1)))
質問で提案した2つの方法(と表示f
)のうち、最初の方法の方が高速です(を使用)。g
timeit
data=rand(4000);
nani=randi(numel(data),1,500);
data(nani)=NaN;
f= @() find(~isnan(sum(data, 2)));
g= @() find(all(~isnan(data), 2));
h= @() find(~isnan(data*zeros(size(data,2),1)));
timeit(f)
ans =
0.0263
timeit(g)
ans =
0.1489
timeit(h)
ans =
0.0146
nan
密度が十分に高い場合は、ダブルループが最速の方法になります。これは、最初の行nan
が見つかるとすぐに行の検索を破棄できるためです。たとえば、次の速度テストについて考えてみます。
%# Preallocate some parameters
T = 5000; %# Number of rows
N = 500; %# Number of columns
X = randi(5, T, N); %# Sample data matrix
M = 100; %# Number of simulation iterations
X(X == 1) = nan; %# Randomly set some elements of X to nan
%# Your first method
tic
for m = 1:M
Soln1 = find(~isnan(sum(X, 2)));
end
toc
%# Your second method
tic
for m = 1:M
Soln2 = find(all(~isnan(X), 2));
end
toc
%# A double loop
tic
for m = 1:M
Soln3 = ones(T, 1);
for t = 1:T
for n = 1:N
if isnan(X(t, n))
Soln3(t) = 0;
break
end
end
end
Soln3 = find(Soln3);
end
toc
結果は次のとおりです。
Elapsed time is 0.164880 seconds.
Elapsed time is 0.218950 seconds.
Elapsed time is 0.068168 seconds. %# The double loop method
もちろん、nan
このシミュレーションでは密度が非常に高いため、どの行もnan
空いていません。しかし、あなたnan
はあなたのマトリックスの密度について何も言わなかったので、私は一般的な消費と熟考のためにこの答えを投稿すると思いました:-)
インデックスで何をしたいのか詳しく教えてください
time = cputime;
A = rand(1000,100); % Some matrix data
for i = 1:100
A(randi(20,1,100)) = NaN; % Randomly assigned NaN
B = isnan(A); % B has 0 and 1
C = A(B == 0); % C has all ~NaN elements
ind(i,:) = find(B == 1); % ind has all NaN indices
end
disp(cputime-time)
ループで100回、0.1404秒
any()
all()
またはよりも高速ですsum()
。試す:
idx = find(~any(isnan(data), 2));
訂正:sum()
アプローチはより速いようです:
idx = find(~isnan(sum(data, 2)));