我想以最快的方式找到没有任何 NaN 的行的索引,因为我需要这样做数千次。到目前为止,我已经尝试了以下两种方法:
find(~isnan(sum(data, 2)));
find(all(~isnan(data), 2));
有没有一种聪明的方法可以加快速度,或者这是最好的方法吗?数据矩阵的维度通常是千乘百。
我想以最快的方式找到没有任何 NaN 的行的索引,因为我需要这样做数千次。到目前为止,我已经尝试了以下两种方法:
find(~isnan(sum(data, 2)));
find(all(~isnan(data), 2));
有没有一种聪明的方法可以加快速度,或者这是最好的方法吗?数据矩阵的维度通常是千乘百。
编辑: 矩阵乘法可以比求和快,因此对于超过 500 x500 个元素的矩阵(在我的 Matlab 2012a 机器中),运算速度几乎快两倍。所以我的解决方案是:
find(~isnan(data*zeros(size(data,2),1)))
在您在问题中建议的两种方法(表示为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
你的矩阵的密度,所以我想我会发布这个答案以供一般消费和沉思:-)
any()
比all()
或快sum()
。尝试:
idx = find(~any(isnan(data), 2));
更正:似乎sum()
方法更快:
idx = find(~isnan(sum(data, 2)));
你能告诉更多关于你想用索引做什么
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 秒