具有不连续间隔的matlab histc

时间:2013-12-18 16:56:16

标签: matlab histogram

过去几天我遇到了这个问题!所以,任何帮助将不胜感激。

问题:


我有一个巨大的不连续间隔列表,其中约有80000个,范围在1到2.5亿之间。而且我有一组更大的数字(一个大约2亿个元素的向量),它们分布在相同的范围内,即1到2.5亿。好像这不够复杂,这些间隔中的一些可能会重叠,但大多数间隔预计会不连续。

现在我想做一个直方图计数,说明每个区间内向量的元素数量。如果这些只是连续的间隔(没有间隙),那么可以使用histc。即使间隔保证总是不连续的(即有间隙),我仍然可以使用histc并抛出间隙中的计数。但由于我没有保证间隔总是不连续的,我很难过。

到目前为止,我尝试了两种方法来解决这个问题:

1)简单地遍历间隔,并在for循环内进行求和(向量> = start& vector< = end)。这绝对是缓慢的。

2)像这样使用cellfun或arrayfun:cellfun(@(L,U)sum(histc(vector,[L U])),Strts,Ends);其中Strts和Ends是定义间隔的单元格数组。

虽然第二个解决方案需要几个小时,但由于我需要为数百个大型数据集执行此操作,所以我负担不起时间。

那么,有更好的方法吗?

非常感谢任何帮助!

谢谢!

3 个答案:

答案 0 :(得分:1)

bsxfun怎么样?

sum(bsxfun(@gt, vector(:), start(:).') & bsxfun(@le, vector(:), stop(:).'))

如果您有内存限制,则可能需要将vector分成块并将所有部分结果汇总起来:

chunksize = 1e4; %// set as allowed by your memory
total = zeros(1,length(start)); %// initiallize
vector = vector(:); %// make column vector
for cut = 1:chunksize:length(vector)
    total = total + sum(bsxfun(@gt, vector(cut+(0:chunksize-1)), start(:).') & bsxfun(@le, vector(cut+(0:chunksize-1)), stop(:).'));
end

答案 1 :(得分:0)

由于您的数字比间隔多得多,最好的方法是选择最快的解决方案来处理所有数字,这可能是通过使用histc(用C语言编写)然后做的您可以根据需要对间隔和直方图进行大量的预处理和后处理,因为任何花在这些上的时间无论如何都可以忽略不计。

我的想法是将区间的所有起点和终点边放在一个有序向量edges中,删除所有重复项,然后用这些边做histc。要获得每个区间的总计数,您只需将区间两侧的索引查找到edges向量中,并总结形成区间的所有单个区间(因为原始区间可能会被切成几个区间)由于重叠的箱子)。像这样(未经测试):

edges = unique([start(:); stop(:)]); % should be sorted

counts = histc(data, edges); % should dominate running time

% find indices of start and stop vectors in edges,
% this should use binary search into sorted vectors, so reasonably fast
[~, istart] = ismember(start, edges);
[~, istop] = ismember(stop, edges);

interval_counts = arrayfun(@(low, hi) sum(counts(low:high-1)), istart, istop);

如果数字量太大而无法放入内存(可能是你从文件中读取它们),那么直接用块(伪代码)进行直方图计算:

counts = 0;
while any_chunks_left()
    counts = counts + histc(get_chunk());
end

假设这个有效,这个解决方案应该使用与max(chunksize, ninterval)成比例的内存量,这比Luis和Oleg的解决方案要少得多。我想总运行时间仅受histc的速度限制。

答案 2 :(得分:0)

以下是我对此的最后看法:

我尝试使用bsxfun函数,但由于我正在处理的大尺寸,我的内存相当快。

因此,实际运作的最简单的技术是:

BINVec = zeros(1,Siz_Including_All_Intvls,'uint8'); 
BINVec(vector) = 1; 
SumVec = cellfun(@(L,U) sum(BINVec(L:U)), strts, ends);

其中strts和ends定义单元格数组中的间隔。

这段代码非常快,我想在几分钟内完成我想要处理的所有数据集的结果!我学到的经验:有时,最被低估的解决方案是效果最好的解决方案。虽然上面的内容让我感到震惊,但我只是认为这个想法非常缓慢。

我确实从你的答案中了解了bsxfun的使用,我个人也喜欢Bas的解决方案!将记住未来!

就这个实例而言,我使用上述方法解决了它。

非常感谢您的投入!

节日快乐!