首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >find()与for循环的性能比较

find()与for循环的性能比较
EN

Stack Overflow用户
提问于 2010-10-22 07:32:59
回答 3查看 737关注 0票数 1

我有一个很大的(4000个值)未排序的正态分布点集合。我将这些数据点都放入限制在BinLimit数组中的存储箱中。然后,我会将每一个bin中的值数列成表格。

X是原始数据的数组,N是数据点的数量。所需的仓位数(TotalBins)由用户指定。

方法#1

代码语言:javascript
复制
for i=1:TotalBins
    Freq(i) = length(find(X >= BinLimit(j) & X <= BinLimit(j+1)));
    j = j + 1;
end

方法#2:

代码语言:javascript
复制
sort(X);

for i=1:N
    if (X(i) >= BinLimit(j) && X(i) <= BinLimit(j+1))
        Freq(j) = freq(j) + 1;
    elseif (j < TotalBins)
        Freq(j+1) = freq(j+1) + 1;
        j = j + 1;
    end
end

现在,我知道第一个解决方案更慢-对于Total Bins (25-50)的正常值,它大约慢8倍,但我想知道是否有比我在方法2中所做的更快、更有效的解决方案。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-10-22 07:40:58

使用histc

对于向量X,

N= HISTC(X,EDGES)计算X中落在边向量(必须包含单调非递减值)元素之间的值的数量。N是包含这些计数的长度(边)向量。N(k)如果边(K) <= X(i) <边(k+1),则计数值X(i)。最后一个框将计算与边匹配的X的任何值(结束)。边值之外的值不会被计算在内。在边中使用-inf和inf可包含所有非NaN值。

例如。

代码语言:javascript
复制
BinLimit = sort(rand(50,1));
X = rand(4000,1);
Freq = histc(X,BinLimit);

为了好玩:

代码语言:javascript
复制
%%# Generating data
X = rand(1000000,1);
BinLimit = sort(rand(50,1));

%%# OP's method
disp('Method #1');
disp('=========');
tic;
j =1;
TotalBins = numel(BinLimit)-1;
for i=1:TotalBins
    Freq(i) = length(find(X >= BinLimit(j) & X <= BinLimit(j+1)));
    j = j + 1;
end
toc

%%# histc
disp('histc');
disp('=====');
tic;
histc(X,BinLimit);
toc

%%# My method
disp('Alternative');
disp('===========');
tic;
TotalBins = numel(BinLimit)-1;
Freq = zeros(TotalBins,1);
for i = 1:TotalBins
    Freq(i) = sum(X >= BinLimit(i) & X <= BinLimit(i+1));
end
toc

跑了几次热身后:

代码语言:javascript
复制
Method #1
=========
Elapsed time is 0.803120 seconds.
histc
=====
Elapsed time is 0.030633 seconds.
Alternative
===========
Elapsed time is 0.704808 seconds.
票数 4
EN

Stack Overflow用户

发布于 2010-10-22 08:15:52

除了使用HISTC之外,这里还有一个矢量化的单行解决方案:

代码语言:javascript
复制
X = randn(4000,1);                %# column vector
BinLimits = linspace(-4,4,10);    %# row vector

Freq = sum( bsxfun(@ge, X, BinLimits(1:end-1)) & bsxfun(@le, X, BinLimits(2:end)) )

请注意,它并不节省空间,因为它创建了一个大小为:length(X) by length(BinLimits)-1的矩阵

票数 2
EN

Stack Overflow用户

发布于 2012-09-26 21:26:26

我认为当你检查X是否属于一个bin时,你可能有一个错误。对于落入BinLimits的X值,您可能会得到多个存储箱。

代码语言:javascript
复制
X >= BinLimit(j) & X <= BinLimit(j+1)

无论如何,既然你要求一个循环解决方案,这里有一个比你的方法2执行得更好的解决方案。

代码语言:javascript
复制
j=1;
i=1;
while i<=N
    while i<=N && X(i)<=BinLimit(j+1)
        i=i+1;
    end
    Freq(j) = i-1;
    j = j+1;
end
Freq=diff([0 Freq]);

它需要对X进行排序,就像在您的代码中一样。下面是用于排序X数组的所有讨论方法的时序(对于排序的X,histc也更快,因此这是一个公平的比较):

代码语言:javascript
复制
Sort
===========
Elapsed time is 0.019205 seconds.
Method #1
=========
Elapsed time is 0.209979 seconds.
histc
=====
Elapsed time is 0.009595 seconds.
Alternative
===========
Elapsed time is 0.228400 seconds.
Method 2
===========
Elapsed time is 0.025400 seconds.
my method
===========
Elapsed time is 0.011920 seconds.
bsxfun by Amro
===========
Elapsed time is 0.179937 seconds.

如你所见,这种循环结构的性能几乎和histc一样好(差25%)。

这是针对排序的X的(排序时间也在上面的结果中给出)。下面是未排序数组的histc结果(与上面相同的X,用随机排列进行排列)

代码语言:javascript
复制
histc
=====
Elapsed time is 0.030367 seconds.

正如您所看到的,对已排序的数组同时执行排序和histc的时间与对未排序的数组运行histc的时间相似。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3992833

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档