使用 MATLAB 对两个向量进行计数
counting over two vectors using MATLAB
我尝试编译下面的代码,但它不起作用。基本上,我想计算 a 中小于或等于 x 中每个元素的元素数。请帮忙
a = exprnd(1,10000, 1);
x = 0:0.02:10;
for i = 1:length(x);
count = 0;
for j = 1:length(a);
if (a(j) <= x(i))
count = count + 1;
end
end
end
使用矢量化的简单方法:
count=zeros(length(x),1);
for ii=1:length(x)
count(ii)=count(ii)+sum(a<=x(ii));
end
对于您的情况,bsxfun()
可以让事情变得更简单。
你可以试试这个:
result = sum(bsxfun(@le, a(:), x(:).'));
使您的方法奏效:
首先我们修正你原来的方法:
a = exprnd(1,10000, 1);
x = 0:0.02:10;
count = zeros(size(x)); %%// <= Preallocate the count-vector
for i = 1:length(x);
%%// <= removed the line "count = 0"
for j = 1:length(a);
if (a(j) <= x(i))
count(i) = count(i) + 1; %%// <= Changed count to count(i)
end
end
end
这将使您的方法奏效。如果你想为相对较大的向量 a
和 x
计算这个,这会很慢,因为整体复杂度是 O(n^2)
。 (假设 n==length(x)==length(a)
。)
您可以使用不同的方法来加快运行时间:
复杂性方法 O(n*log(n))
使用 sort
:
这里是一个复杂度为O(n*log(n))
的算法,而不是O(n^2)
。
它基于 Matlab 的 sort
是稳定的并且位置被返回。假设x
已经排序,如果再对[a(:); x(:)]
进行排序,x(1)
的新位置将是1
加上a
小于等于的元素个数至 x(1)
。 x(2)
的新位置将是 2
加上 a
小于或等于 x(2)
的元素数。所以a
中小于x(i)
的元素个数等于x(i)
的新位置减去i
.
function aSmallerThanxMat = aSmallerThanx(a, x)
%%// Remember dimension of x
dimX = size(x);
%%// Sort x and remember original ordering Ix
[xsorted, Ix] = sort(x(:));
%%// How many as are smaller than sortedX
[~,Iaxsorted] = sort([a(:); xsorted(:)]);
Iaxsortedinv(Iaxsorted) = 1:numel(Iaxsorted);
aSmallerThanSortedx = Iaxsortedinv(numel(a)+1:end)-(1:numel(xsorted));
%%// Get original ordering of x back
aSmallerThanx(Ix) = aSmallerThanSortedx;
%%// Reshape x to original array size
aSmallerThanxMat = reshape(aSmallerThanx, dimX);
这种方法可能有点难以掌握,但对于大向量,你会得到相当大的加速。
使用 sort
和 for
的类似方法:
这种方法的概念非常相似,但更传统的使用循环:
首先我们对 x
和 a
进行排序。然后我们单步执行x(i_x)
。如果 x(i_x)
大于当前的 a(i_a)
,我们增加 i_a
。如果小于当前i_a
,那么i_a-1
就是a
中小于等于x(i_x)
.
的元素个数
function aSmallerThanx = aSmallerThanx(a, x)
asorted = sort(a(:));
[xsorted, Ix] = sort(x(:));
aSmallerThanx = zeros(size(x));
i_a = 1;
for i_x = 1:numel(xsorted)
for i_a = i_a:numel(asorted)+1
if i_a>numel(asorted) || xsorted(i_x)<asorted(i_a)
aSmallerThanx(Ix(i_x)) = i_a-1;
break
end
end
end
方法使用 histc
:
这个更好:它在 x
的值之间创建 bin,计算落入每个 bin 的 a
的值,然后从左边开始对它们求和。
function result = aSmallerThanx(a, x)
[xsorted, Ix] = sort(x(:));
bincounts = histc(a, [-Inf; xsorted]);
result(Ix) = cumsum(bincounts(1:end-1));
比较:
这是您的方法的运行时比较,Ander Biguri 的 for+sum
循环方法,mehmet 的 bsxfun
方法,这两种方法使用 sort
和 histc
方法:
对于长度为 16384 的向量,histc
方法比原始方法快 2300 倍。
我尝试编译下面的代码,但它不起作用。基本上,我想计算 a 中小于或等于 x 中每个元素的元素数。请帮忙
a = exprnd(1,10000, 1);
x = 0:0.02:10;
for i = 1:length(x);
count = 0;
for j = 1:length(a);
if (a(j) <= x(i))
count = count + 1;
end
end
end
使用矢量化的简单方法:
count=zeros(length(x),1);
for ii=1:length(x)
count(ii)=count(ii)+sum(a<=x(ii));
end
对于您的情况,bsxfun()
可以让事情变得更简单。
你可以试试这个:
result = sum(bsxfun(@le, a(:), x(:).'));
使您的方法奏效:
首先我们修正你原来的方法:
a = exprnd(1,10000, 1);
x = 0:0.02:10;
count = zeros(size(x)); %%// <= Preallocate the count-vector
for i = 1:length(x);
%%// <= removed the line "count = 0"
for j = 1:length(a);
if (a(j) <= x(i))
count(i) = count(i) + 1; %%// <= Changed count to count(i)
end
end
end
这将使您的方法奏效。如果你想为相对较大的向量 a
和 x
计算这个,这会很慢,因为整体复杂度是 O(n^2)
。 (假设 n==length(x)==length(a)
。)
您可以使用不同的方法来加快运行时间:
复杂性方法 O(n*log(n))
使用 sort
:
这里是一个复杂度为O(n*log(n))
的算法,而不是O(n^2)
。
它基于 Matlab 的 sort
是稳定的并且位置被返回。假设x
已经排序,如果再对[a(:); x(:)]
进行排序,x(1)
的新位置将是1
加上a
小于等于的元素个数至 x(1)
。 x(2)
的新位置将是 2
加上 a
小于或等于 x(2)
的元素数。所以a
中小于x(i)
的元素个数等于x(i)
的新位置减去i
.
function aSmallerThanxMat = aSmallerThanx(a, x)
%%// Remember dimension of x
dimX = size(x);
%%// Sort x and remember original ordering Ix
[xsorted, Ix] = sort(x(:));
%%// How many as are smaller than sortedX
[~,Iaxsorted] = sort([a(:); xsorted(:)]);
Iaxsortedinv(Iaxsorted) = 1:numel(Iaxsorted);
aSmallerThanSortedx = Iaxsortedinv(numel(a)+1:end)-(1:numel(xsorted));
%%// Get original ordering of x back
aSmallerThanx(Ix) = aSmallerThanSortedx;
%%// Reshape x to original array size
aSmallerThanxMat = reshape(aSmallerThanx, dimX);
这种方法可能有点难以掌握,但对于大向量,你会得到相当大的加速。
使用 sort
和 for
的类似方法:
这种方法的概念非常相似,但更传统的使用循环:
首先我们对 x
和 a
进行排序。然后我们单步执行x(i_x)
。如果 x(i_x)
大于当前的 a(i_a)
,我们增加 i_a
。如果小于当前i_a
,那么i_a-1
就是a
中小于等于x(i_x)
.
function aSmallerThanx = aSmallerThanx(a, x)
asorted = sort(a(:));
[xsorted, Ix] = sort(x(:));
aSmallerThanx = zeros(size(x));
i_a = 1;
for i_x = 1:numel(xsorted)
for i_a = i_a:numel(asorted)+1
if i_a>numel(asorted) || xsorted(i_x)<asorted(i_a)
aSmallerThanx(Ix(i_x)) = i_a-1;
break
end
end
end
方法使用 histc
:
这个更好:它在 x
的值之间创建 bin,计算落入每个 bin 的 a
的值,然后从左边开始对它们求和。
function result = aSmallerThanx(a, x)
[xsorted, Ix] = sort(x(:));
bincounts = histc(a, [-Inf; xsorted]);
result(Ix) = cumsum(bincounts(1:end-1));
比较:
这是您的方法的运行时比较,Ander Biguri 的 for+sum
循环方法,mehmet 的 bsxfun
方法,这两种方法使用 sort
和 histc
方法:
对于长度为 16384 的向量,histc
方法比原始方法快 2300 倍。