【问题标题】:counting over two vectors using MATLAB使用 MATLAB 计算两个向量
【发布时间】:2015-03-19 01:37:57
【问题描述】:

我尝试编译下面的代码,但它不起作用。基本上,我想计算 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

【问题讨论】:

  • 哦!我想这可以通过cumsumhistc 来完成。
  • 另外:我感觉你可能真的在寻找ecdf
  • 请澄清这个问题的应用,以便我们可以将问题标题更改为更易于未来用户搜索的内容。
  • 类似问题:1,2,3,还有 numpy 函数searchsorted,做类似的事情
  • 是的.. 试图获取 cdf

标签: matlab


【解决方案1】:

在你的情况下,bsxfun() 可以让事情变得更容易。

你可以试试这个:

result = sum(bsxfun(@le, a(:), x(:).'));

【讨论】:

  • 我认为bsxfun 是我根本不使用的唯一Matlabs 功能之一,每次我阅读SO 中的答案时,我都会想:伙计,你错了!很好的答案。
  • @AnderBiguri - 当你使用它一次时,你永远不会放弃,请确保! ((:
  • bsxfun 我经常使用。它在图像过滤中非常有用。我从 Divakar 学会了如何有效地使用它:)。顺便说一句,+1。
  • @rayryeng - 我们这里有高手 :D 这是一个非常有用的功能,与单行命令一样使用循环。
  • @mehmet - 我同意这一点:) 我还建议学习的一个功能是accumarray。我从 chappjc 学习了如何使用它,并且我提出的许多优雅的解决方案都使用它。我最喜欢的一个是计算两个图像之间的联合熵:stackoverflow.com/questions/23691398/…
【解决方案2】:

让你的方法奏效:

首先我们修正你原来的方法:

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

这将使您的方法奏效。如果你想为相对较大的向量 ax 计算它,这将非常慢,因为整体复杂度是 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);

这种方法可能有点难以掌握,但对于大型向量,您将获得相当大的加速。

使用sortfor 的类似方法:

这种方法的概念非常相似,但更传统的使用循环: 首先我们对xa 进行排序。然后我们单步执行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 Bigurifor+sum 循环方法,mehmetbsxfun 方法,这两种方法使用 @987654366 @ 和 histc 方法: 对于长度为 16384 的向量,histc 方法比原始方法快 2300 倍。

【讨论】:

  • @Divakar:可能有点过分,但推动解决方案有点让人上瘾。 ;-) 我仍在努力为这个问题找出一个更好的标题和描述,以防将来有人想搜索这个...... :-S
  • 推动替代解决方案,也许比已经发布的更有效,并且在此过程中学习是在 SO 上学习的最好的东西之一。你对标题的看法是对的,它需要一个更具代表性的标题。
【解决方案3】:

使用矢量化的简单方法:

 count=zeros(length(x),1);  
 for ii=1:length(x)
       count(ii)=count(ii)+sum(a<=x(ii));
 end

【讨论】:

  • 我认为zeros(length(x)) 是一个错误,因为它会生成一个方阵。你可以改用zeros(size(x));
猜你喜欢
  • 2017-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-27
相关资源
最近更新 更多