Matlab 在排序向量中定位位置,快速
我在matlab中有一个排序向量,称之为Matlab 在排序向量中定位位置,快速,matlab,performance,Matlab,Performance,我在matlab中有一个排序向量,称之为F,在这个例子中,它是这样给出的: F = [1,2,3,4,5,6,7,8,9,10]; 我还有一个任意矩阵A,元素的间隔为0-10,比如: A = [1.5,9.1,5.2;2.3,0.4,7.9]; 然后我对矩阵I感兴趣,对于A中的每个条目,它告诉我它属于F中的哪个区间,作为下限,在这种情况下: I = [1,9,5;2,0,7]; 我知道,在这种情况下,它可以通过四舍五入获得,但我在寻找一般情况。我已经有一段代码为我解决了这个问题,它是:
F
,在这个例子中,它是这样给出的:
F = [1,2,3,4,5,6,7,8,9,10];
我还有一个任意矩阵A
,元素的间隔为0-10,比如:
A = [1.5,9.1,5.2;2.3,0.4,7.9];
然后我对矩阵I
感兴趣,对于A
中的每个条目,它告诉我它属于F
中的哪个区间,作为下限,在这种情况下:
I = [1,9,5;2,0,7];
我知道,在这种情况下,它可以通过四舍五入获得,但我在寻找一般情况。我已经有一段代码为我解决了这个问题,它是:
I = zeros(size(A));
X(A<F(1)) = 0;
for i = 2:length(F)
X(A<F(i) & A>F(i-1)) = i-1;
end
end
I=0(大小(A));
X(A=F,1)-1,A)代码>但是这比上面的逻辑版本慢100倍左右
有什么建议吗?这就行了,而且可能很快:
result = reshape(sum(bsxfun(@lt, F(:), A(:).'), 1), size(A));
我假设间隔定义为(a,b)。对于[a,b],将@lt
替换为@le
利用向量已排序这一事实,进行某种排序可能会更快。这有可能是在内部进行的。第三个输出提供了您想要的:
[~, ~, result] = histcounts(A, F);
下面是一个使用浮点和int输入的解决方案。
超出插值为NaN
的间隔范围的值,因此在应用插值之前,应决定如何使用thode值
使用带有选项的interp
对数据应用最近邻插值
function out = histcount3(v , interval)
%compute center of bins
centers = interval(1:end-1) + diff(interval)/2;
%apply nearest neighbor interpolation
out = interp1(centers,interval(1:end-1),v(:),'nearest');
end
如果区间为整数类型且区间范围合理,则可能的快速解决方案为:
function out = histcount2(v , interval)
v= max(interval(1),v);
v=min(interval(end),v);
count= diff(interval);
count(end) = count(end)+1;
r = repelem(interval(1:end-1), count);
out = r(floor(v)-interval(1)+1);
end
和以前一样,应该决定如何处理超出范围的值。我用间隔的最小值和最大值替换这些值。
我在Octave中进行了测试,但Octave没有histcount
的hist
定时功能,前提是我认为它与histcount
的算法相同,但结果不同。您可以使用histcount
运行基准测试以获得正确的结果:
F = unique(randi([1000 100000],1,1000));
A = rand(100000,3)*101000;
disp('------histcount2:--------')
tic
reshape(histcount2(A(:),F),size(A));
toc
disp('------histcount3:--------')
tic
reshape(histcount3(A(:),F),size(A));
toc
disp('------hist:--------')
tic
hist(A(:),F);
toc
disp('------bsxfun:--------')
tic
reshape(sum(bsxfun(@le, F(:), A(:).'), 1), size(A));
toc
结果:
------histcount2:repelem--------
Elapsed time is 0.00749207 seconds.
------histcount3:interpolation--------
Elapsed time is 0.042104 seconds.
------hist:--------
Elapsed time is 0.135928 seconds.
------bsxfun:--------
Elapsed time is 0.516705 seconds.
正如matlab所建议的,对@Luis Mendo建议的一点改进应该是使用离散化
根据文件
discretize的行为与histcounts函数的行为类似。使用histcounts可查找每个存储箱中的元素数。另一方面,使用discretize可查找每个元素所属的存储箱(不计算)
从而将代码行转换为:
I = discretize(A,F)-1;
虽然必须在变量F
中指定一个最小值。因此,继续我在原始文章中的示例,它会将F
变成:
F = [0,1,2,3,4,5,6,7,8,9,10];
然而,我的测试运行表明,histcounts
始终要快一点。您的第一个建议基本上是我的行X(AF(i-1))内部发生的事情=i-1;
因此它们同样快。然而,histcounts
是一个绝妙的主意,可以将运行时间减少约90%。如果有人有更好的方法,我会等到明天再回答。不幸的是,F
不限于整数,因此count
由浮点数和repelem
w组成使用非整数秒参数返回错误。是否可以修复?我对修复非常感兴趣,因为您的解决方案似乎比histcounts
@NickyMattsson的速度快十倍。让我想想有更好的解决方案