在Matlab中找到没有NaN的行的最快方法

时间:2013-02-05 06:16:07

标签: performance matlab matrix vectorization

我想以最快的方式找到没有任何NaN的行的索引,因为我需要做数千次。到目前为止,我尝试了以下两种方法:

find(~isnan(sum(data, 2)));
find(all(~isnan(data), 2));

有没有一种聪明的方法可以加快速度,或者这是最好的方法吗?数据矩阵的维度通常是数千或数百。

4 个答案:

答案 0 :(得分:4)

修改 矩阵乘法可以比和更快,因此对于500 x500以上的矩阵(在我的Matlab 2012a机器中),操作几乎快两倍。所以我的解决方案是:

find(~isnan(data*zeros(size(data,2),1)))

在您提出的两种方法(表示为fg)中,第一种方法更快(使用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

答案 1 :(得分:2)

如果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密度的任何信息,所以我想我会把这个答案发布给一般的消费和沉思: - )

答案 2 :(得分:0)

您能否详细说明您希望如何处理指数

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秒

答案 3 :(得分:0)

any()all()sum()快。 尝试:

idx = find(~any(isnan(data), 2));

更正:似乎sum()方法更快:

idx = find(~isnan(sum(data, 2)));